From d180bc6df297422f189ffd08a0dd558bfbeba1ca Mon Sep 17 00:00:00 2001 From: Sean Hall Date: Sun, 15 Jan 2023 19:17:29 -0600 Subject: Add netfx:DotNetCoreSdkFeatureBandSearch. 7058 --- src/api/wix/WixToolset.Data/WixVersionLabel.cs | 43 --- src/ext/NetFx/be/detectnetcore.cpp | 91 +----- src/ext/NetFx/be/detectnetcoresdk.cpp | 99 +------ src/ext/NetFx/be/detectnetcoresdkfeatureband.cpp | 55 ++++ src/ext/NetFx/be/detectnetcoresdkfeatureband.h | 9 + src/ext/NetFx/be/netfxbe.vcxproj | 4 + src/ext/NetFx/be/netfxsearch.cpp | 32 +- src/ext/NetFx/be/netfxsearch.h | 10 +- src/ext/NetFx/be/precomp.h | 2 + src/ext/NetFx/be/runnetcoresearch.cpp | 102 +++++++ src/ext/NetFx/be/runnetcoresearch.h | 9 + src/ext/NetFx/netcoresearch/netcoresearch.cpp | 327 ++++++++++++--------- .../UsingDotNetCorePackages/BundleLatest.wxs | 2 + .../UsingDotNetCorePackages/BundleLatest_x64.wxs | 1 + .../UsingDotNetCorePackages/NetCore3.1.12_x64.wxs | 17 +- .../UsingDotNetCorePackages/NetCore3.1.12_x86.wxs | 17 +- .../UsingDotNetCorePackages/NetCore3_Platform.wxi | 5 +- src/ext/NetFx/wixext/NetFxCompiler.cs | 190 +++++++++++- .../NetFxNetCoreSearchSdkFeatureBandSymbol.cs | 71 +++++ .../wixext/Symbols/NetFxNetCoreSearchSdkSymbol.cs | 25 +- .../NetFx/wixext/Symbols/NetfxSymbolDefinitions.cs | 7 +- .../TestBA/TestBAWixlib/NetCore6.0.9_x86.wxs | 21 +- .../TestBA/TestBAWixlib/NetCore6_Platform.wxi | 7 +- .../TestBA/TestBAWixlib_x64/NetCore6.0.9_x64.wxs | 21 +- .../TestData/TestBA/TestBAWixlib_x64/WixBA_x64.wxs | 6 +- 25 files changed, 745 insertions(+), 428 deletions(-) delete mode 100644 src/api/wix/WixToolset.Data/WixVersionLabel.cs create mode 100644 src/ext/NetFx/be/detectnetcoresdkfeatureband.cpp create mode 100644 src/ext/NetFx/be/detectnetcoresdkfeatureband.h create mode 100644 src/ext/NetFx/be/runnetcoresearch.cpp create mode 100644 src/ext/NetFx/be/runnetcoresearch.h create mode 100644 src/ext/NetFx/wixext/Symbols/NetFxNetCoreSearchSdkFeatureBandSymbol.cs diff --git a/src/api/wix/WixToolset.Data/WixVersionLabel.cs b/src/api/wix/WixToolset.Data/WixVersionLabel.cs deleted file mode 100644 index c4227c49..00000000 --- a/src/api/wix/WixToolset.Data/WixVersionLabel.cs +++ /dev/null @@ -1,43 +0,0 @@ -// 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. - -namespace WixToolset.Data -{ - using System; - - /// - /// Label in a WixVersion. - /// - [CLSCompliant(false)] - public class WixVersionLabel - { - /// - /// Creates a string only version label. - /// - /// String value for version label. - public WixVersionLabel(string label) - { - this.Label = label; - } - - /// - /// Creates a string version label with numeric value. - /// - /// String value for version label. - /// Numeric value for the version label. - public WixVersionLabel(string label, uint? numeric) - { - this.Label = label; - this.Numeric = numeric; - } - - /// - /// Gets the string label value. - /// - public string Label { get; set; } - - /// - /// Gets the optional numeric label value. - /// - public uint? Numeric { get; set; } - } -} diff --git a/src/ext/NetFx/be/detectnetcore.cpp b/src/ext/NetFx/be/detectnetcore.cpp index aeb04203..3ed26549 100644 --- a/src/ext/NetFx/be/detectnetcore.cpp +++ b/src/ext/NetFx/be/detectnetcore.cpp @@ -12,18 +12,7 @@ HRESULT DetectNetCore( { HRESULT hr = S_OK; LPCWSTR wzRuntimeType = NULL; - LPCWSTR wzPlatformName = NULL; - LPWSTR sczExePath = NULL; - LPWSTR sczCommandLine = NULL; - HANDLE hProcess = NULL; - HANDLE hStdOutErr = INVALID_HANDLE_VALUE; - BYTE* rgbOutput = NULL; - DWORD cbOutput = 0; - DWORD cbTotalRead = 0; - DWORD cbRead = 0; - DWORD dwExitCode = 0; - - ReleaseNullStr(*psczLatestVersion); + LPWSTR sczArguments = NULL; switch (runtimeType) { @@ -41,80 +30,14 @@ HRESULT DetectNetCore( break; } - switch (platform) - { - case NETFX_NET_CORE_PLATFORM_ARM64: - wzPlatformName = L"arm64"; - break; - case NETFX_NET_CORE_PLATFORM_X64: - wzPlatformName = L"x64"; - break; - case NETFX_NET_CORE_PLATFORM_X86: - wzPlatformName = L"x86"; - break; - default: - BextExitWithRootFailure(hr, E_INVALIDARG, "Unknown platform: %u", platform); - break; - } - - hr = StrAllocFormatted(&sczExePath, L"%ls%ls\\netcoresearch.exe", wzBaseDirectory, wzPlatformName); - BextExitOnFailure(hr, "Failed to build netcoresearch.exe path."); - - hr = StrAllocFormatted(&sczCommandLine, L"\"%ls\" runtime %ls %ls", sczExePath, wzMajorVersion, wzRuntimeType); - BextExitOnFailure(hr, "Failed to build netcoresearch.exe command line."); - - hr = ProcExecute(sczExePath, sczCommandLine, &hProcess, NULL, &hStdOutErr); - if (HRESULT_FROM_WIN32(ERROR_EXE_MACHINE_TYPE_MISMATCH) == hr) - { - ExitFunction1(hr = S_FALSE); - } - BextExitOnFailure(hr, "Failed to run: %ls", sczCommandLine); - - cbOutput = 64; + hr = StrAllocFormatted(&sczArguments, L"runtime %ls %ls", wzMajorVersion, wzRuntimeType); + BextExitOnFailure(hr, "Failed to build runtime netcoresearch.exe arguments."); - rgbOutput = reinterpret_cast(MemAlloc(cbOutput, TRUE)); - BextExitOnNull(rgbOutput, hr, E_OUTOFMEMORY, "Failed to alloc output string."); - - while (::ReadFile(hStdOutErr, rgbOutput + cbTotalRead, cbOutput - cbTotalRead, &cbRead, NULL)) - { - cbTotalRead += cbRead; - - if (cbTotalRead == cbOutput) - { - cbOutput *= 2; - - LPVOID pvNew = MemReAlloc(rgbOutput, cbOutput, TRUE); - BextExitOnNull(pvNew, hr, E_OUTOFMEMORY, "Failed to realloc output string."); - - rgbOutput = reinterpret_cast(pvNew); - } - } - - if (ERROR_BROKEN_PIPE != ::GetLastError()) - { - BextExitWithLastError(hr, "Failed to read netcoresearch.exe output."); - } - - hr = ProcWaitForCompletion(hProcess, INFINITE, &dwExitCode); - BextExitOnFailure(hr, "Failed to wait for netcoresearch.exe to exit."); - - if (0 != dwExitCode) - { - BextExitWithRootFailure(hr, E_UNEXPECTED, "netcoresearch.exe failed with exit code: 0x%x\r\nOutput:\r\n%hs", dwExitCode, rgbOutput); - } - - if (*rgbOutput) - { - hr = StrAllocStringAnsi(psczLatestVersion, reinterpret_cast(rgbOutput), 0, CP_UTF8); - BextExitOnFailure(hr, "Failed to widen output string: %hs", rgbOutput); - } + hr = RunNetCoreSearch(platform, wzBaseDirectory, sczArguments, psczLatestVersion); + BextExitOnFailure(hr, "Failed to run netcoresearch.exe for runtime."); LExit: - ReleaseFileHandle(hStdOutErr); - ReleaseHandle(hProcess); - ReleaseMem(rgbOutput); - ReleaseStr(sczCommandLine); - ReleaseStr(sczExePath); + ReleaseStr(sczArguments); return hr; } @@ -136,5 +59,7 @@ HRESULT NetfxPerformDetectNetCore( BextExitOnFailure(hr, "Failed to set variable '%ls' to '%ls'", wzVariable, sczLatestVersion); LExit: + ReleaseStr(sczLatestVersion); + return hr; } diff --git a/src/ext/NetFx/be/detectnetcoresdk.cpp b/src/ext/NetFx/be/detectnetcoresdk.cpp index 08b18334..332d8712 100644 --- a/src/ext/NetFx/be/detectnetcoresdk.cpp +++ b/src/ext/NetFx/be/detectnetcoresdk.cpp @@ -4,99 +4,22 @@ HRESULT DetectNetCoreSdk( __in NETFX_NET_CORE_PLATFORM platform, - __in LPCWSTR wzVersion, + __in LPCWSTR wzMajorVersion, __in LPCWSTR wzBaseDirectory, __inout LPWSTR* psczLatestVersion ) { HRESULT hr = S_OK; - LPCWSTR wzPlatformName = NULL; - LPWSTR sczExePath = NULL; - LPWSTR sczCommandLine = NULL; - HANDLE hProcess = NULL; - HANDLE hStdOutErr = INVALID_HANDLE_VALUE; - BYTE* rgbOutput = NULL; - DWORD cbOutput = 0; - DWORD cbTotalRead = 0; - DWORD cbRead = 0; - DWORD dwExitCode = 0; + LPWSTR sczArguments = NULL; - ReleaseNullStr(*psczLatestVersion); + hr = StrAllocFormatted(&sczArguments, L"sdk %ls", wzMajorVersion); + BextExitOnFailure(hr, "Failed to build sdk netcoresearch.exe arguments."); - switch (platform) - { - case NETFX_NET_CORE_PLATFORM_ARM64: - wzPlatformName = L"arm64"; - break; - case NETFX_NET_CORE_PLATFORM_X64: - wzPlatformName = L"x64"; - break; - case NETFX_NET_CORE_PLATFORM_X86: - wzPlatformName = L"x86"; - break; - default: - BextExitWithRootFailure(hr, E_INVALIDARG, "Unknown platform: %u", platform); - break; - } - - hr = StrAllocFormatted(&sczExePath, L"%ls%ls\\netcoresearch.exe", wzBaseDirectory, wzPlatformName); - BextExitOnFailure(hr, "Failed to build netcoresearch.exe path."); - - hr = StrAllocFormatted(&sczCommandLine, L"\"%ls\" sdk %ls", sczExePath, wzVersion); - BextExitOnFailure(hr, "Failed to build netcoresearch.exe command line."); - - hr = ProcExecute(sczExePath, sczCommandLine, &hProcess, NULL, &hStdOutErr); - if (HRESULT_FROM_WIN32(ERROR_EXE_MACHINE_TYPE_MISMATCH) == hr) - { - ExitFunction1(hr = S_FALSE); - } - BextExitOnFailure(hr, "Failed to run: %ls", sczCommandLine); - - cbOutput = 64; - - rgbOutput = static_cast(MemAlloc(cbOutput, TRUE)); - BextExitOnNull(rgbOutput, hr, E_OUTOFMEMORY, "Failed to alloc output string."); - - while (::ReadFile(hStdOutErr, rgbOutput + cbTotalRead, cbOutput - cbTotalRead, &cbRead, NULL)) - { - cbTotalRead += cbRead; - - if (cbTotalRead == cbOutput) - { - cbOutput *= 2; - - const LPVOID pvNew = MemReAlloc(rgbOutput, cbOutput, TRUE); - BextExitOnNull(pvNew, hr, E_OUTOFMEMORY, "Failed to realloc output string."); - - rgbOutput = static_cast(pvNew); - } - } - - if (ERROR_BROKEN_PIPE != ::GetLastError()) - { - BextExitWithLastError(hr, "Failed to read netcoresearch.exe output."); - } - - hr = ProcWaitForCompletion(hProcess, INFINITE, &dwExitCode); - BextExitOnFailure(hr, "Failed to wait for netcoresearch.exe to exit."); - - if (0 != dwExitCode) - { - BextExitWithRootFailure(hr, E_UNEXPECTED, "netcoresearch.exe failed with exit code: 0x%x\r\nOutput:\r\n%hs", dwExitCode, rgbOutput); - } - - if (*rgbOutput) - { - hr = StrAllocStringAnsi(psczLatestVersion, reinterpret_cast(rgbOutput), 0, CP_UTF8); - BextExitOnFailure(hr, "Failed to widen output string: %hs", rgbOutput); - } + hr = RunNetCoreSearch(platform, wzBaseDirectory, sczArguments, psczLatestVersion); + BextExitOnFailure(hr, "Failed to run netcoresearch.exe for sdk."); LExit: - ReleaseFileHandle(hStdOutErr); - ReleaseHandle(hProcess); - ReleaseMem(rgbOutput); - ReleaseStr(sczCommandLine); - ReleaseStr(sczExePath); + ReleaseStr(sczArguments); return hr; } @@ -109,14 +32,16 @@ HRESULT NetfxPerformDetectNetCoreSdk( ) { HRESULT hr = S_OK; - LPWSTR sczLatestVersion = nullptr; - const auto& searchParams = pSearch->NetCoreSdkSearch; - hr = DetectNetCoreSdk(searchParams.platform, searchParams.sczVersion, wzBaseDirectory, &sczLatestVersion); + LPWSTR sczLatestVersion = NULL; + + hr = DetectNetCoreSdk(pSearch->NetCoreSdkSearch.platform, pSearch->NetCoreSdkSearch.sczMajorVersion, wzBaseDirectory, &sczLatestVersion); BextExitOnFailure(hr, "DetectNetCoreSdk failed."); hr = pEngine->SetVariableVersion(wzVariable, sczLatestVersion); BextExitOnFailure(hr, "Failed to set variable '%ls' to '%ls'", wzVariable, sczLatestVersion); LExit: + ReleaseStr(sczLatestVersion); + return hr; } diff --git a/src/ext/NetFx/be/detectnetcoresdkfeatureband.cpp b/src/ext/NetFx/be/detectnetcoresdkfeatureband.cpp new file mode 100644 index 00000000..d48c7a85 --- /dev/null +++ b/src/ext/NetFx/be/detectnetcoresdkfeatureband.cpp @@ -0,0 +1,55 @@ +// 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" + +HRESULT DetectNetCoreSdkFeatureBand( + __in NETFX_NET_CORE_PLATFORM platform, + __in LPCWSTR wzMajorVersion, + __in LPCWSTR wzMinorVersion, + __in LPCWSTR wzPatchVersion, + __in LPCWSTR wzBaseDirectory, + __inout LPWSTR* psczLatestVersion + ) +{ + HRESULT hr = S_OK; + LPWSTR sczArguments = NULL; + + hr = StrAllocFormatted(&sczArguments, L"sdkfeatureband %ls %ls %ls", wzMajorVersion, wzMinorVersion, wzPatchVersion); + BextExitOnFailure(hr, "Failed to build sdkfeatureband netcoresearch.exe arguments."); + + hr = RunNetCoreSearch(platform, wzBaseDirectory, sczArguments, psczLatestVersion); + BextExitOnFailure(hr, "Failed to run netcoresearch.exe for sdkfeatureband."); + +LExit: + ReleaseStr(sczArguments); + + return hr; +} + +HRESULT NetfxPerformDetectNetCoreSdkFeatureBand( + __in LPCWSTR wzVariable, + __in NETFX_SEARCH* pSearch, + __in IBundleExtensionEngine* pEngine, + __in LPCWSTR wzBaseDirectory + ) +{ + HRESULT hr = S_OK; + LPWSTR sczLatestVersion = NULL; + + hr = DetectNetCoreSdkFeatureBand( + pSearch->NetCoreSdkFeatureBandSearch.platform, + pSearch->NetCoreSdkFeatureBandSearch.sczMajorVersion, + pSearch->NetCoreSdkFeatureBandSearch.sczMinorVersion, + pSearch->NetCoreSdkFeatureBandSearch.sczPatchVersion, + wzBaseDirectory, + &sczLatestVersion); + BextExitOnFailure(hr, "DetectNetCoreSdkFeatureBand failed."); + + hr = pEngine->SetVariableVersion(wzVariable, sczLatestVersion); + BextExitOnFailure(hr, "Failed to set variable '%ls' to '%ls'", wzVariable, sczLatestVersion); + +LExit: + ReleaseStr(sczLatestVersion); + + return hr; +} diff --git a/src/ext/NetFx/be/detectnetcoresdkfeatureband.h b/src/ext/NetFx/be/detectnetcoresdkfeatureband.h new file mode 100644 index 00000000..1f92cd58 --- /dev/null +++ b/src/ext/NetFx/be/detectnetcoresdkfeatureband.h @@ -0,0 +1,9 @@ +#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 NetfxPerformDetectNetCoreSdkFeatureBand( + __in LPCWSTR wzVariable, + __in NETFX_SEARCH* pSearch, + __in IBundleExtensionEngine* pEngine, + __in LPCWSTR wzBaseDirectory + ); diff --git a/src/ext/NetFx/be/netfxbe.vcxproj b/src/ext/NetFx/be/netfxbe.vcxproj index 0408da72..94026960 100644 --- a/src/ext/NetFx/be/netfxbe.vcxproj +++ b/src/ext/NetFx/be/netfxbe.vcxproj @@ -48,20 +48,24 @@ + Create + + + diff --git a/src/ext/NetFx/be/netfxsearch.cpp b/src/ext/NetFx/be/netfxsearch.cpp index 671e7546..ffbf6ee0 100644 --- a/src/ext/NetFx/be/netfxsearch.cpp +++ b/src/ext/NetFx/be/netfxsearch.cpp @@ -15,7 +15,7 @@ STDMETHODIMP NetfxSearchParseFromXml( BSTR bstrNodeName = NULL; // Select Netfx search nodes. - hr = XmlSelectNodes(pixnBundleExtension, L"NetFxNetCoreSearch|NetFxNetCoreSdkSearch", &pixnNodes); + hr = XmlSelectNodes(pixnBundleExtension, L"NetFxNetCoreSearch|NetFxNetCoreSdkSearch|NetFxNetCoreSdkFeatureBandSearch", &pixnNodes); BextExitOnFailure(hr, "Failed to select Netfx search nodes."); // Get Netfx search node count. @@ -72,9 +72,30 @@ STDMETHODIMP NetfxSearchParseFromXml( hr = XmlGetAttributeUInt32(pixnNode, L"Platform", reinterpret_cast(&netCoreSdkSearch.platform)); BextExitOnFailure(hr, "Failed to get @Platform."); - // @Version - hr = XmlGetAttributeEx(pixnNode, L"Version", &netCoreSdkSearch.sczVersion); - BextExitOnFailure(hr, "Failed to get @Version."); + // @MajorVersion + hr = XmlGetAttributeEx(pixnNode, L"MajorVersion", &netCoreSdkSearch.sczMajorVersion); + BextExitOnFailure(hr, "Failed to get @MajorVersion."); + } + else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, bstrNodeName, -1, L"NetFxNetCoreSdkFeatureBandSearch", -1)) + { + pSearch->Type = NETFX_SEARCH_TYPE_NET_CORE_SDK_FEATURE_BAND_SEARCH; + + auto& netCoreSdkSearch = pSearch->NetCoreSdkFeatureBandSearch; + // @Platform + hr = XmlGetAttributeUInt32(pixnNode, L"Platform", reinterpret_cast(&netCoreSdkSearch.platform)); + BextExitOnFailure(hr, "Failed to get @Platform."); + + // @MajorVersion + hr = XmlGetAttributeEx(pixnNode, L"MajorVersion", &netCoreSdkSearch.sczMajorVersion); + BextExitOnFailure(hr, "Failed to get @MajorVersion."); + + // @MinorVersion + hr = XmlGetAttributeEx(pixnNode, L"MinorVersion", &netCoreSdkSearch.sczMinorVersion); + BextExitOnFailure(hr, "Failed to get @MinorVersion."); + + // @PatchVersion + hr = XmlGetAttributeEx(pixnNode, L"PatchVersion", &netCoreSdkSearch.sczPatchVersion); + BextExitOnFailure(hr, "Failed to get @PatchVersion."); } else { @@ -132,6 +153,9 @@ STDMETHODIMP NetfxSearchExecute( case NETFX_SEARCH_TYPE_NET_CORE_SDK_SEARCH: hr = NetfxPerformDetectNetCoreSdk(wzVariable, pSearch, pEngine, wzBaseDirectory); break; + case NETFX_SEARCH_TYPE_NET_CORE_SDK_FEATURE_BAND_SEARCH: + hr = NetfxPerformDetectNetCoreSdkFeatureBand(wzVariable, pSearch, pEngine, wzBaseDirectory); + break; default: hr = E_UNEXPECTED; } diff --git a/src/ext/NetFx/be/netfxsearch.h b/src/ext/NetFx/be/netfxsearch.h index f4e4db01..5793dd55 100644 --- a/src/ext/NetFx/be/netfxsearch.h +++ b/src/ext/NetFx/be/netfxsearch.h @@ -9,6 +9,7 @@ enum NETFX_SEARCH_TYPE NETFX_SEARCH_TYPE_NONE, NETFX_SEARCH_TYPE_NET_CORE_SEARCH, NETFX_SEARCH_TYPE_NET_CORE_SDK_SEARCH, + NETFX_SEARCH_TYPE_NET_CORE_SDK_FEATURE_BAND_SEARCH, }; enum NETFX_NET_CORE_RUNTIME_TYPE @@ -44,8 +45,15 @@ typedef struct _NETFX_SEARCH struct { NETFX_NET_CORE_PLATFORM platform; - LPWSTR sczVersion; + LPWSTR sczMajorVersion; } NetCoreSdkSearch; + struct + { + NETFX_NET_CORE_PLATFORM platform; + LPWSTR sczMajorVersion; + LPWSTR sczMinorVersion; + LPWSTR sczPatchVersion; + } NetCoreSdkFeatureBandSearch; }; } NETFX_SEARCH; diff --git a/src/ext/NetFx/be/precomp.h b/src/ext/NetFx/be/precomp.h index 4a774200..c164834d 100644 --- a/src/ext/NetFx/be/precomp.h +++ b/src/ext/NetFx/be/precomp.h @@ -31,4 +31,6 @@ #include "netfxsearch.h" #include "detectnetcore.h" #include "detectnetcoresdk.h" +#include "detectnetcoresdkfeatureband.h" #include "NetfxBundleExtension.h" +#include "runnetcoresearch.h" diff --git a/src/ext/NetFx/be/runnetcoresearch.cpp b/src/ext/NetFx/be/runnetcoresearch.cpp new file mode 100644 index 00000000..8f38e0d2 --- /dev/null +++ b/src/ext/NetFx/be/runnetcoresearch.cpp @@ -0,0 +1,102 @@ +// 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" + +HRESULT RunNetCoreSearch( + __in NETFX_NET_CORE_PLATFORM platform, + __in LPCWSTR wzBaseDirectory, + __in LPCWSTR wzArguments, + __inout LPWSTR* psczLatestVersion + ) +{ + HRESULT hr = S_OK; + LPCWSTR wzPlatformName = NULL; + LPWSTR sczExePath = NULL; + LPWSTR sczCommandLine = NULL; + HANDLE hProcess = NULL; + HANDLE hStdOutErr = INVALID_HANDLE_VALUE; + BYTE* rgbOutput = NULL; + DWORD cbOutput = 0; + DWORD cbTotalRead = 0; + DWORD cbRead = 0; + DWORD dwExitCode = 0; + + ReleaseNullStr(*psczLatestVersion); + + switch (platform) + { + case NETFX_NET_CORE_PLATFORM_ARM64: + wzPlatformName = L"arm64"; + break; + case NETFX_NET_CORE_PLATFORM_X64: + wzPlatformName = L"x64"; + break; + case NETFX_NET_CORE_PLATFORM_X86: + wzPlatformName = L"x86"; + break; + default: + BextExitWithRootFailure(hr, E_INVALIDARG, "Unknown platform: %u", platform); + break; + } + + hr = StrAllocFormatted(&sczExePath, L"%ls%ls\\netcoresearch.exe", wzBaseDirectory, wzPlatformName); + BextExitOnFailure(hr, "Failed to build netcoresearch.exe path."); + + hr = StrAllocFormatted(&sczCommandLine, L"\"%ls\" %ls", sczExePath, wzArguments); + BextExitOnFailure(hr, "Failed to build netcoresearch.exe command line."); + + hr = ProcExecute(sczExePath, sczCommandLine, &hProcess, NULL, &hStdOutErr); + if (HRESULT_FROM_WIN32(ERROR_EXE_MACHINE_TYPE_MISMATCH) == hr) + { + ExitFunction1(hr = S_FALSE); + } + BextExitOnFailure(hr, "Failed to run: %ls", sczCommandLine); + + cbOutput = 64; + + rgbOutput = reinterpret_cast(MemAlloc(cbOutput, TRUE)); + BextExitOnNull(rgbOutput, hr, E_OUTOFMEMORY, "Failed to alloc output string."); + + while (::ReadFile(hStdOutErr, rgbOutput + cbTotalRead, cbOutput - cbTotalRead, &cbRead, NULL)) + { + cbTotalRead += cbRead; + + if (cbTotalRead == cbOutput) + { + cbOutput *= 2; + + LPVOID pvNew = MemReAlloc(rgbOutput, cbOutput, TRUE); + BextExitOnNull(pvNew, hr, E_OUTOFMEMORY, "Failed to realloc output string."); + + rgbOutput = reinterpret_cast(pvNew); + } + } + + if (ERROR_BROKEN_PIPE != ::GetLastError()) + { + BextExitWithLastError(hr, "Failed to read netcoresearch.exe output."); + } + + hr = ProcWaitForCompletion(hProcess, INFINITE, &dwExitCode); + BextExitOnFailure(hr, "Failed to wait for netcoresearch.exe to exit."); + + if (0 != dwExitCode) + { + BextExitWithRootFailure(hr, E_UNEXPECTED, "netcoresearch.exe failed with exit code: 0x%x\r\nOutput:\r\n%hs", dwExitCode, rgbOutput); + } + + if (*rgbOutput) + { + hr = StrAllocStringAnsi(psczLatestVersion, reinterpret_cast(rgbOutput), 0, CP_UTF8); + BextExitOnFailure(hr, "Failed to widen output string: %hs", rgbOutput); + } + +LExit: + ReleaseFileHandle(hStdOutErr); + ReleaseHandle(hProcess); + ReleaseMem(rgbOutput); + ReleaseStr(sczCommandLine); + ReleaseStr(sczExePath); + + return hr; +} diff --git a/src/ext/NetFx/be/runnetcoresearch.h b/src/ext/NetFx/be/runnetcoresearch.h new file mode 100644 index 00000000..78e6b24a --- /dev/null +++ b/src/ext/NetFx/be/runnetcoresearch.h @@ -0,0 +1,9 @@ +#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 RunNetCoreSearch( + __in NETFX_NET_CORE_PLATFORM platform, + __in LPCWSTR wzBaseDirectory, + __in LPCWSTR wzArguments, + __inout LPWSTR* psczLatestVersion + ); diff --git a/src/ext/NetFx/netcoresearch/netcoresearch.cpp b/src/ext/NetFx/netcoresearch/netcoresearch.cpp index 5cf6d10b..8c788461 100644 --- a/src/ext/NetFx/netcoresearch/netcoresearch.cpp +++ b/src/ext/NetFx/netcoresearch/netcoresearch.cpp @@ -2,137 +2,155 @@ #include "precomp.h" -enum class NETCORESEARCHKIND +enum class NETCORESEARCHTYPE { None, Runtime, Sdk, + SdkFeatureBand, }; struct NETCORESEARCH_STATE { - NETCORESEARCHKIND Kind = NETCORESEARCHKIND::None; - union - { - struct - { - LPCWSTR wzTargetName; - DWORD dwMajorVersion; - } Runtime; - struct - { - DWORD dwMajorVersion; - DWORD dwMinorVersion; - DWORD dwFeatureBand; - } - Sdk; - } Data; + NETCORESEARCHTYPE type; + HRESULT hrSearch; VERUTIL_VERSION* pVersion; + + struct + { + LPCWSTR wzTargetName; + DWORD dwMajorVersion; + } Runtime; + struct + { + DWORD dwMajorVersion; + } Sdk; + struct + { + DWORD dwMajorVersion; + DWORD dwMinorVersion; + DWORD dwPatchVersion; + } SdkFeatureBand; }; +static HRESULT GetSearchStateFromArguments( + __in int argc, + __in LPWSTR argv[], + __in NETCORESEARCH_STATE* pSearchState + ); static HRESULT GetDotnetEnvironmentInfo( - __in NETCORESEARCH_STATE& pSearchState, - __inout VERUTIL_VERSION** ppVersion + __in NETCORESEARCH_STATE* pSearchState ); static void HOSTFXR_CALLTYPE GetDotnetEnvironmentInfoResult( __in const hostfxr_dotnet_environment_info* pInfo, __in LPVOID pvContext ); -bool string_equal_invariant(__in PCWSTR const x,__in PCWSTR const y) { return CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, x, -1, y, -1); } - -HRESULT get_search_state_from_arguments(__in int argc, __in LPWSTR argv[], __out NETCORESEARCH_STATE& searchState); - int __cdecl wmain(int argc, LPWSTR argv[]) { HRESULT hr = S_OK; - VERUTIL_VERSION* pVersion = NULL; - NETCORESEARCH_STATE searchState = {}; - - ::SetConsoleCP(CP_UTF8); + NETCORESEARCH_STATE searchState = { }; ConsoleInitialize(); - hr = get_search_state_from_arguments(argc, argv, OUT searchState); - if (FAILED(hr)) - { - ConsoleExitOnFailure(hr, CONSOLE_COLOR_RED, "Failed to parse arguments."); - } + hr = GetSearchStateFromArguments(argc, argv, &searchState); + ConsoleExitOnFailure(hr, CONSOLE_COLOR_RED, "Failed to parse arguments."); - hr = GetDotnetEnvironmentInfo(searchState, &pVersion); + hr = GetDotnetEnvironmentInfo(&searchState); + ConsoleExitOnFailure(hr, CONSOLE_COLOR_RED, "Failed to search."); - - if (pVersion) + if (searchState.pVersion) { - ConsoleWriteW(CONSOLE_COLOR_NORMAL, pVersion->sczVersion); + ConsoleWriteW(CONSOLE_COLOR_NORMAL, searchState.pVersion->sczVersion); } LExit: - ReleaseVerutilVersion(pVersion); + ReleaseVerutilVersion(searchState.pVersion); ConsoleUninitialize(); return hr; } -HRESULT get_search_state_from_arguments(int argc, LPWSTR argv[], __out NETCORESEARCH_STATE& searchState) +HRESULT GetSearchStateFromArguments( + __in int argc, + __in LPWSTR argv[], + __in NETCORESEARCH_STATE* pSearchState + ) { HRESULT hr = S_OK; - searchState = {}; - const auto searchKind = argv[1]; + LPCWSTR wzSearchKind = NULL; - if (argc < 3) + if (argc < 2) { ExitFunction1(hr = E_INVALIDARG); } + wzSearchKind = argv[1]; - if (string_equal_invariant(searchKind, L"runtime")) + if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, wzSearchKind, -1, L"runtime", -1)) { if (argc != 4) { ExitFunction1(hr = E_INVALIDARG); } - searchState.Kind = NETCORESEARCHKIND::Runtime; - const PCWSTR majorVersion = argv[2]; - const PCWSTR targetName = argv[3]; + LPCWSTR wzMajorVersion = argv[2]; + LPCWSTR wzTargetName = argv[3]; - auto& data = searchState.Data.Runtime; + pSearchState->type = NETCORESEARCHTYPE::Runtime; - data.wzTargetName = targetName; - hr = StrStringToUInt32(majorVersion, 0, reinterpret_cast(&data.dwMajorVersion)); - ConsoleExitOnFailure(hr, CONSOLE_COLOR_RED, "Failed to get target version from: %ls", majorVersion); + hr = StrStringToUInt32(wzMajorVersion, 0, reinterpret_cast(&pSearchState->Runtime.dwMajorVersion)); + ConsoleExitOnFailure(hr, CONSOLE_COLOR_RED, "Failed to get target version from: %ls", wzMajorVersion); + + pSearchState->Runtime.wzTargetName = wzTargetName; } - else if(string_equal_invariant(searchKind, L"sdk")) + else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, wzSearchKind, -1, L"sdk", -1)) { - searchState.Kind = NETCORESEARCHKIND::Sdk; + if (argc != 3) + { + ExitFunction1(hr = E_INVALIDARG); + } + + LPCWSTR wzMajorVersion = argv[2]; - const PCWSTR version = argv[2]; + pSearchState->type = NETCORESEARCHTYPE::Sdk; - VERUTIL_VERSION* sdkVersion = nullptr; - hr = VerParseVersion(version, 0, FALSE, &sdkVersion); - if (FAILED(hr)) + hr = StrStringToUInt32(wzMajorVersion, 0, reinterpret_cast(&pSearchState->Sdk.dwMajorVersion)); + ConsoleExitOnFailure(hr, CONSOLE_COLOR_RED, "Failed to get sdk major version from: %ls", wzMajorVersion); + } + else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, wzSearchKind, -1, L"sdkfeatureband", -1)) + { + if (argc != 5) { - ConsoleExitOnFailure(hr, CONSOLE_COLOR_RED, "Failed to parse version from: %ls", version); + ExitFunction1(hr = E_INVALIDARG); } - auto& data = searchState.Data.Sdk; + LPCWSTR wzMajorVersion = argv[2]; + LPCWSTR wzMinorVersion = argv[3]; + LPCWSTR wzPatchVersion = argv[4]; + + pSearchState->type = NETCORESEARCHTYPE::SdkFeatureBand; - data.dwMajorVersion = sdkVersion->dwMajor; - data.dwMinorVersion = sdkVersion->dwMinor; - data.dwFeatureBand = sdkVersion->dwPatch; + hr = StrStringToUInt32(wzMajorVersion, 0, reinterpret_cast(&pSearchState->SdkFeatureBand.dwMajorVersion)); + ConsoleExitOnFailure(hr, CONSOLE_COLOR_RED, "Failed to get major version from: %ls", wzMajorVersion); - VerFreeVersion(sdkVersion); + hr = StrStringToUInt32(wzMinorVersion, 0, reinterpret_cast(&pSearchState->SdkFeatureBand.dwMinorVersion)); + ConsoleExitOnFailure(hr, CONSOLE_COLOR_RED, "Failed to get minor version from: %ls", wzMinorVersion); + + hr = StrStringToUInt32(wzPatchVersion, 0, reinterpret_cast(&pSearchState->SdkFeatureBand.dwPatchVersion)); + ConsoleExitOnFailure(hr, CONSOLE_COLOR_RED, "Failed to get patch version from: %ls", wzPatchVersion); + } + else + { + pSearchState->type = NETCORESEARCHTYPE::None; + ExitFunction1(hr = E_INVALIDARG); } LExit: return hr; } - - static HRESULT GetDotnetEnvironmentInfo( - __in NETCORESEARCH_STATE& state, - __inout VERUTIL_VERSION** ppVersion + __in NETCORESEARCH_STATE* pState ) { HRESULT hr = S_OK; @@ -156,17 +174,13 @@ static HRESULT GetDotnetEnvironmentInfo( pfnGetDotnetEnvironmentInfo = (hostfxr_get_dotnet_environment_info_fn)::GetProcAddress(hModule, "hostfxr_get_dotnet_environment_info"); ConsoleExitOnNullWithLastError(pfnGetDotnetEnvironmentInfo, hr, CONSOLE_COLOR_RED, "Failed to get address for hostfxr_get_dotnet_environment_info."); - hr = pfnGetDotnetEnvironmentInfo(NULL, NULL, GetDotnetEnvironmentInfoResult, &state); + hr = pfnGetDotnetEnvironmentInfo(NULL, NULL, GetDotnetEnvironmentInfoResult, pState); ConsoleExitOnFailure(hr, CONSOLE_COLOR_RED, "Failed to get .NET Core environment info."); - if (state.pVersion) - { - *ppVersion = state.pVersion; - state.pVersion = NULL; - } + hr = pState->hrSearch; + ConsoleExitOnFailure(hr, CONSOLE_COLOR_RED, "Failed to process .NET Core environment info."); LExit: - ReleaseVerutilVersion(state.pVersion); ReleaseStr(sczHostfxrPath); ReleaseStr(sczProcessPath); @@ -178,108 +192,145 @@ LExit: return hr; } -bool matches_feature_band(const int requested, const int actual) +static HRESULT PerformRuntimeSearch( + __in const hostfxr_dotnet_environment_info* pInfo, + __in DWORD dwMajorVersion, + __in LPCWSTR wzTargetName, + __inout VERUTIL_VERSION** ppVersion + ) { - // we have not requested a match on feature band, so skip the check - if (requested == 0) return true; + HRESULT hr = S_OK; + VERUTIL_VERSION* pFrameworkVersion = NULL; + int nCompare = 0; + + for (size_t i = 0; i < pInfo->framework_count; ++i) + { + const hostfxr_dotnet_environment_framework_info* pFrameworkInfo = pInfo->frameworks + i; + ReleaseVerutilVersion(pFrameworkVersion); + + if (CSTR_EQUAL != ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, wzTargetName, -1, pFrameworkInfo->name, -1)) + { + continue; + } + + hr = VerParseVersion(pFrameworkInfo->version, 0, FALSE, &pFrameworkVersion); + ConsoleExitOnFailure(hr, CONSOLE_COLOR_RED, "Failed to parse framework version: %ls", pFrameworkInfo->version); + + if (pFrameworkVersion->dwMajor != dwMajorVersion) + { + continue; + } + + if (*ppVersion) + { + hr = VerCompareParsedVersions(*ppVersion, pFrameworkVersion, &nCompare); + ConsoleExitOnFailure(hr, CONSOLE_COLOR_RED, "Failed to compare versions."); - const int requestedBand = requested / 100; - const int actualBand = actual / 100; + if (nCompare > -1) + { + continue; + } + } - if (actualBand != requestedBand) return false; + ReleaseVerutilVersion(*ppVersion); + *ppVersion = pFrameworkVersion; + pFrameworkVersion = NULL; + } - return actual >= requested; +LExit: + ReleaseVerutilVersion(pFrameworkVersion); + + return hr; } -static void HOSTFXR_CALLTYPE GetDotnetEnvironmentInfoResult( +static HRESULT PerformSdkSearch( __in const hostfxr_dotnet_environment_info* pInfo, - __in LPVOID pvContext + __in BOOL fFeatureBand, + __in DWORD dwMajorVersion, + __in DWORD dwMinorVersion, + __in DWORD dwPatchVersion, + __inout VERUTIL_VERSION** ppVersion ) { - NETCORESEARCH_STATE* pState = static_cast(pvContext); HRESULT hr = S_OK; - VERUTIL_VERSION* pDotnetVersion = nullptr; + VERUTIL_VERSION* pSdkVersion = NULL; int nCompare = 0; + DWORD dwRequestedBand = dwPatchVersion / 100; - - if (pState->Kind == NETCORESEARCHKIND::Sdk) + for (size_t i = 0; i < pInfo->sdk_count; ++i) { - auto& sdkData = pState->Data.Sdk; - for (size_t i = 0; i < pInfo->sdk_count; ++i) - { - const hostfxr_dotnet_environment_sdk_info* pSdkInfo = pInfo->sdks + i; - ReleaseVerutilVersion(pDotnetVersion); + const hostfxr_dotnet_environment_sdk_info* pSdkInfo = pInfo->sdks + i; + ReleaseVerutilVersion(pSdkVersion); - hr = VerParseVersion(pSdkInfo->version, 0, FALSE, &pDotnetVersion); - ConsoleExitOnFailure(hr, CONSOLE_COLOR_RED, "Failed to parse sdk version: %ls", pSdkInfo->version); + hr = VerParseVersion(pSdkInfo->version, 0, FALSE, &pSdkVersion); + ConsoleExitOnFailure(hr, CONSOLE_COLOR_RED, "Failed to parse sdk version: %ls", pSdkInfo->version); - if (pDotnetVersion->dwMajor != sdkData.dwMajorVersion) - { - continue; - } - if (!matches_feature_band(sdkData.dwFeatureBand, pDotnetVersion->dwPatch)) + if (pSdkVersion->dwMajor != dwMajorVersion) + { + continue; + } + + if (fFeatureBand) + { + if (pSdkVersion->dwMinor != dwMinorVersion) { continue; } - if (pState->pVersion) + if ((pSdkVersion->dwPatch / 100) != dwRequestedBand) { - hr = VerCompareParsedVersions(pState->pVersion, pDotnetVersion, &nCompare); - ConsoleExitOnFailure(hr, CONSOLE_COLOR_RED, "Failed to compare versions."); - - if (nCompare > -1) - { - continue; - } + continue; } - - ReleaseVerutilVersion(pState->pVersion); - pState->pVersion = pDotnetVersion; - pDotnetVersion = nullptr; } - } - else if(pState->Kind == NETCORESEARCHKIND::Runtime) - { - auto& runtimeData = pState->Data.Runtime; - for (size_t i = 0; i < pInfo->framework_count; ++i) + + if (*ppVersion) { - const hostfxr_dotnet_environment_framework_info* pFrameworkInfo = pInfo->frameworks + i; - ReleaseVerutilVersion(pDotnetVersion); + hr = VerCompareParsedVersions(*ppVersion, pSdkVersion, &nCompare); + ConsoleExitOnFailure(hr, CONSOLE_COLOR_RED, "Failed to compare versions."); - if (string_equal_invariant(runtimeData.wzTargetName, pFrameworkInfo->name)) + if (nCompare > -1) { continue; } + } - hr = VerParseVersion(pFrameworkInfo->version, 0, FALSE, &pDotnetVersion); - ConsoleExitOnFailure(hr, CONSOLE_COLOR_RED, "Failed to parse framework version: %ls", pFrameworkInfo->version); + ReleaseVerutilVersion(*ppVersion); + *ppVersion = pSdkVersion; + pSdkVersion = NULL; + } - if (pDotnetVersion->dwMajor != runtimeData.dwMajorVersion) - { - continue; - } +LExit: + ReleaseVerutilVersion(pSdkVersion); - if (pState->pVersion) - { - hr = VerCompareParsedVersions(pState->pVersion, pDotnetVersion, &nCompare); - ConsoleExitOnFailure(hr, CONSOLE_COLOR_RED, "Failed to compare versions."); + return hr; +} - if (nCompare > -1) - { - continue; - } - } +static void HOSTFXR_CALLTYPE GetDotnetEnvironmentInfoResult( + __in const hostfxr_dotnet_environment_info* pInfo, + __in LPVOID pvContext + ) +{ + NETCORESEARCH_STATE* pState = static_cast(pvContext); + HRESULT hr = S_OK; - ReleaseVerutilVersion(pState->pVersion); - pState->pVersion = pDotnetVersion; - pDotnetVersion = nullptr; - } + if (pState->type == NETCORESEARCHTYPE::Sdk) + { + hr = PerformSdkSearch(pInfo, FALSE, pState->Sdk.dwMajorVersion, 0, 0, &pState->pVersion); + } + else if (pState->type == NETCORESEARCHTYPE::SdkFeatureBand) + { + hr = PerformSdkSearch(pInfo, TRUE, pState->SdkFeatureBand.dwMajorVersion, pState->SdkFeatureBand.dwMinorVersion, pState->SdkFeatureBand.dwPatchVersion, &pState->pVersion); + } + else if (pState->type == NETCORESEARCHTYPE::Runtime) + { + hr = PerformRuntimeSearch(pInfo, pState->Runtime.dwMajorVersion, pState->Runtime.wzTargetName, &pState->pVersion); } else { - ConsoleWriteError(E_INVALIDARG, CONSOLE_COLOR_RED, "Invalid NETCORESEARCHKIND."); + hr = E_INVALIDARG; + ConsoleExitOnFailure(hr, CONSOLE_COLOR_RED, "Invalid NETCORESEARCHTYPE."); } LExit: - ReleaseVerutilVersion(pDotnetVersion); + pState->hrSearch = hr; } diff --git a/src/ext/NetFx/test/WixToolsetTest.Netfx/TestData/UsingDotNetCorePackages/BundleLatest.wxs b/src/ext/NetFx/test/WixToolsetTest.Netfx/TestData/UsingDotNetCorePackages/BundleLatest.wxs index b7b55747..812f623b 100644 --- a/src/ext/NetFx/test/WixToolsetTest.Netfx/TestData/UsingDotNetCorePackages/BundleLatest.wxs +++ b/src/ext/NetFx/test/WixToolsetTest.Netfx/TestData/UsingDotNetCorePackages/BundleLatest.wxs @@ -7,9 +7,11 @@ + + diff --git a/src/ext/NetFx/test/WixToolsetTest.Netfx/TestData/UsingDotNetCorePackages/BundleLatest_x64.wxs b/src/ext/NetFx/test/WixToolsetTest.Netfx/TestData/UsingDotNetCorePackages/BundleLatest_x64.wxs index 3588686a..a4639d7c 100644 --- a/src/ext/NetFx/test/WixToolsetTest.Netfx/TestData/UsingDotNetCorePackages/BundleLatest_x64.wxs +++ b/src/ext/NetFx/test/WixToolsetTest.Netfx/TestData/UsingDotNetCorePackages/BundleLatest_x64.wxs @@ -7,6 +7,7 @@ + diff --git a/src/ext/NetFx/test/WixToolsetTest.Netfx/TestData/UsingDotNetCorePackages/NetCore3.1.12_x64.wxs b/src/ext/NetFx/test/WixToolsetTest.Netfx/TestData/UsingDotNetCorePackages/NetCore3.1.12_x64.wxs index 74e82405..78444901 100644 --- a/src/ext/NetFx/test/WixToolsetTest.Netfx/TestData/UsingDotNetCorePackages/NetCore3.1.12_x64.wxs +++ b/src/ext/NetFx/test/WixToolsetTest.Netfx/TestData/UsingDotNetCorePackages/NetCore3.1.12_x64.wxs @@ -5,7 +5,7 @@ - + @@ -61,16 +61,17 @@ - + + - - - - + + + + - - + + diff --git a/src/ext/NetFx/test/WixToolsetTest.Netfx/TestData/UsingDotNetCorePackages/NetCore3.1.12_x86.wxs b/src/ext/NetFx/test/WixToolsetTest.Netfx/TestData/UsingDotNetCorePackages/NetCore3.1.12_x86.wxs index 9acc4dc5..69700d80 100644 --- a/src/ext/NetFx/test/WixToolsetTest.Netfx/TestData/UsingDotNetCorePackages/NetCore3.1.12_x86.wxs +++ b/src/ext/NetFx/test/WixToolsetTest.Netfx/TestData/UsingDotNetCorePackages/NetCore3.1.12_x86.wxs @@ -5,7 +5,7 @@ - + @@ -61,16 +61,17 @@ - + + - - - - + + + + - - + + diff --git a/src/ext/NetFx/test/WixToolsetTest.Netfx/TestData/UsingDotNetCorePackages/NetCore3_Platform.wxi b/src/ext/NetFx/test/WixToolsetTest.Netfx/TestData/UsingDotNetCorePackages/NetCore3_Platform.wxi index 2933196d..affe0143 100644 --- a/src/ext/NetFx/test/WixToolsetTest.Netfx/TestData/UsingDotNetCorePackages/NetCore3_Platform.wxi +++ b/src/ext/NetFx/test/WixToolsetTest.Netfx/TestData/UsingDotNetCorePackages/NetCore3_Platform.wxi @@ -21,8 +21,9 @@ - - + + + diff --git a/src/ext/NetFx/wixext/NetFxCompiler.cs b/src/ext/NetFx/wixext/NetFxCompiler.cs index 7a37cf90..c40bc77b 100644 --- a/src/ext/NetFx/wixext/NetFxCompiler.cs +++ b/src/ext/NetFx/wixext/NetFxCompiler.cs @@ -55,6 +55,12 @@ namespace WixToolset.Netfx case "DotNetCoreSdkSearchRef": this.ParseDotNetCoreSdkSearchRefElement(intermediate, section, element); break; + case "DotNetCoreSdkFeatureBandSearch": + this.ParseDotNetCoreSdkFeatureBandSearchElement(intermediate, section, element); + break; + case "DotNetCoreSdkFeatureBandSearchRef": + this.ParseDotNetCoreSdkFeatureBandSearchRefElement(intermediate, section, element); + break; case "DotNetCompatibilityCheck": this.ParseDotNetCompatibilityCheckElement(intermediate, section, element); break; @@ -81,6 +87,12 @@ namespace WixToolset.Netfx case "DotNetCoreSdkSearchRef": this.ParseDotNetCoreSdkSearchRefElement(intermediate, section, element); break; + case "DotNetCoreSdkFeatureBandSearch": + this.ParseDotNetCoreSdkFeatureBandSearchElement(intermediate, section, element); + break; + case "DotNetCoreSdkFeatureBandSearchRef": + this.ParseDotNetCoreSdkFeatureBandSearchRefElement(intermediate, section, element); + break; default: this.ParseHelper.UnexpectedElement(parentElement, element); break; @@ -267,8 +279,8 @@ namespace WixToolset.Netfx string variable = null; string condition = null; string after = null; - NetCoreSdkSearchPlatform? platform = null; - string version = null; + NetCoreSearchPlatform? platform = null; + var majorVersion = CompilerConstants.IntegerNotSet; foreach (var attrib in element.Attributes()) { @@ -293,22 +305,22 @@ namespace WixToolset.Netfx switch (platformValue) { case "arm64": - platform = NetCoreSdkSearchPlatform.Arm64; + platform = NetCoreSearchPlatform.Arm64; break; case "x64": - platform = NetCoreSdkSearchPlatform.X64; + platform = NetCoreSearchPlatform.X64; break; case "x86": - platform = NetCoreSdkSearchPlatform.X86; + platform = NetCoreSearchPlatform.X86; break; default: this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, "Platform", platformValue, "arm64", "x64", "x86")); break; } break; - case "Version": + case "MajorVersion": // .NET Core had a different deployment strategy before .NET Core 3.0 which would require different detection logic. - version = this.ParseHelper.GetAttributeVersionValue(sourceLineNumbers, attrib); + majorVersion = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 3, Int32.MaxValue); break; default: this.ParseHelper.UnexpectedAttribute(element, attrib); @@ -331,16 +343,13 @@ namespace WixToolset.Netfx this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Platform")); } - - if (String.IsNullOrEmpty(version)) + if (majorVersion == CompilerConstants.IntegerNotSet) { - this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Version")); + this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "MajorVersion")); } - - var ver = Version.Parse(version); - if (ver.Major == 4) + else if (majorVersion == 4) { - this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, "Version", version, "3.*", "5+.*")); + this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, "MajorVersion", "4", "3", "5+")); } this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element); @@ -358,7 +367,7 @@ namespace WixToolset.Netfx section.AddSymbol(new NetFxNetCoreSdkSearchSymbol(sourceLineNumbers, id) { Platform = platform.Value, - Version = version, + MajorVersion = majorVersion, }); } } @@ -391,6 +400,157 @@ namespace WixToolset.Netfx this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element); } + private void ParseDotNetCoreSdkFeatureBandSearchElement(Intermediate intermediate, IntermediateSection section, XElement element) + { + var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element); + Identifier id = null; + string variable = null; + string condition = null; + string after = null; + NetCoreSearchPlatform? platform = null; + string version = null; + var majorVersion = 0; + var minorVersion = 0; + var patchVersion = 0; + + foreach (var attrib in element.Attributes()) + { + if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) + { + switch (attrib.Name.LocalName) + { + case "Id": + id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib); + break; + case "Variable": + variable = this.ParseHelper.GetAttributeBundleVariableNameValue(sourceLineNumbers, attrib); + break; + case "Condition": + condition = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); + break; + case "After": + after = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); + break; + case "Platform": + var platformValue = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); + switch (platformValue) + { + case "arm64": + platform = NetCoreSearchPlatform.Arm64; + break; + case "x64": + platform = NetCoreSearchPlatform.X64; + break; + case "x86": + platform = NetCoreSearchPlatform.X86; + break; + default: + this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, "Platform", platformValue, "arm64", "x64", "x86")); + break; + } + break; + case "Version": + version = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); + break; + default: + this.ParseHelper.UnexpectedAttribute(element, attrib); + break; + } + } + else + { + this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib); + } + } + + if (id == null) + { + id = this.ParseHelper.CreateIdentifier("dncsfbs", variable, condition, after); + } + + if (!platform.HasValue) + { + this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Platform")); + } + + if (String.IsNullOrEmpty(version)) + { + this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Version")); + } + else + { + if (!Version.TryParse(version, out var featureBandVersion)) + { + this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, "Version", version, "x.x.x00")); + } + else + { + majorVersion = featureBandVersion.Major; + minorVersion = featureBandVersion.Minor; + patchVersion = featureBandVersion.Build; + + if ((patchVersion % 100) != 0 || featureBandVersion.Revision != -1) + { + this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, "Version", version, "x.x.x00")); + } + + if (majorVersion == 4) + { + this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, "Version", version, "3.*", "5+.*")); + } + } + } + + this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element); + + var bundleExtensionId = this.ParseHelper.CreateIdentifierValueFromPlatform("Wix4NetfxBundleExtension", this.Context.Platform, BurnPlatforms.X86 | BurnPlatforms.X64 | BurnPlatforms.ARM64); + if (bundleExtensionId == null) + { + this.Messaging.Write(ErrorMessages.UnsupportedPlatformForElement(sourceLineNumbers, this.Context.Platform.ToString(), element.Name.LocalName)); + } + + if (!this.Messaging.EncounteredError) + { + this.ParseHelper.CreateWixSearchSymbol(section, sourceLineNumbers, element.Name.LocalName, id, variable, condition, after, bundleExtensionId); + + section.AddSymbol(new NetFxNetCoreSdkFeatureBandSearchSymbol(sourceLineNumbers, id) + { + Platform = platform.Value, + MajorVersion = majorVersion, + MinorVersion = minorVersion, + PatchVersion = patchVersion, + }); + } + } + + private void ParseDotNetCoreSdkFeatureBandSearchRefElement(Intermediate intermediate, IntermediateSection section, XElement element) + { + var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element); + + foreach (var attrib in element.Attributes()) + { + if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) + { + switch (attrib.Name.LocalName) + { + case "Id": + var refId = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib); + this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, NetfxSymbolDefinitions.NetFxNetCoreSdkFeatureBandSearch, refId); + break; + default: + this.ParseHelper.UnexpectedAttribute(element, attrib); + break; + } + } + else + { + this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib); + } + } + + this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element); + } + /// /// Parses a NativeImage element. /// diff --git a/src/ext/NetFx/wixext/Symbols/NetFxNetCoreSearchSdkFeatureBandSymbol.cs b/src/ext/NetFx/wixext/Symbols/NetFxNetCoreSearchSdkFeatureBandSymbol.cs new file mode 100644 index 00000000..ad80f9d2 --- /dev/null +++ b/src/ext/NetFx/wixext/Symbols/NetFxNetCoreSearchSdkFeatureBandSymbol.cs @@ -0,0 +1,71 @@ +// 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. + +namespace WixToolset.Netfx +{ + using WixToolset.Data; + using WixToolset.Netfx.Symbols; + + public static partial class NetfxSymbolDefinitions + { + public static readonly IntermediateSymbolDefinition NetFxNetCoreSdkFeatureBandSearch = new IntermediateSymbolDefinition( + NetfxSymbolDefinitionType.NetFxNetCoreSdkFeatureBandSearch.ToString(), + new[] + { + new IntermediateFieldDefinition(nameof(NetFxNetCoreSdkFeatureBandSearchSymbolFields.Platform), IntermediateFieldType.Number), + new IntermediateFieldDefinition(nameof(NetFxNetCoreSdkFeatureBandSearchSymbolFields.MajorVersion), IntermediateFieldType.Number), + new IntermediateFieldDefinition(nameof(NetFxNetCoreSdkFeatureBandSearchSymbolFields.MinorVersion), IntermediateFieldType.Number), + new IntermediateFieldDefinition(nameof(NetFxNetCoreSdkFeatureBandSearchSymbolFields.PatchVersion), IntermediateFieldType.Number), + }, + typeof(NetFxNetCoreSdkFeatureBandSearchSymbol)); + } +} + +namespace WixToolset.Netfx.Symbols +{ + using WixToolset.Data; + + public enum NetFxNetCoreSdkFeatureBandSearchSymbolFields + { + Platform, + MajorVersion, + MinorVersion, + PatchVersion, + } + + public class NetFxNetCoreSdkFeatureBandSearchSymbol : IntermediateSymbol + { + public NetFxNetCoreSdkFeatureBandSearchSymbol() : base(NetfxSymbolDefinitions.NetFxNetCoreSdkFeatureBandSearch, null, null) + { + } + + public NetFxNetCoreSdkFeatureBandSearchSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(NetfxSymbolDefinitions.NetFxNetCoreSdkFeatureBandSearch, sourceLineNumber, id) + { + } + + public IntermediateField this[NetFxNetCoreSdkFeatureBandSearchSymbolFields index] => this.Fields[(int)index]; + + public NetCoreSearchPlatform Platform + { + get => (NetCoreSearchPlatform)this.Fields[(int)NetFxNetCoreSdkFeatureBandSearchSymbolFields.Platform].AsNumber(); + set => this.Set((int)NetFxNetCoreSdkFeatureBandSearchSymbolFields.Platform, (int)value); + } + + public int MajorVersion + { + get => this.Fields[(int)NetFxNetCoreSdkFeatureBandSearchSymbolFields.MajorVersion].AsNumber(); + set => this.Set((int)NetFxNetCoreSdkFeatureBandSearchSymbolFields.MajorVersion, value); + } + + public int MinorVersion + { + get => this.Fields[(int)NetFxNetCoreSdkFeatureBandSearchSymbolFields.MinorVersion].AsNumber(); + set => this.Set((int)NetFxNetCoreSdkFeatureBandSearchSymbolFields.MinorVersion, value); + } + + public int PatchVersion + { + get => this.Fields[(int)NetFxNetCoreSdkFeatureBandSearchSymbolFields.PatchVersion].AsNumber(); + set => this.Set((int)NetFxNetCoreSdkFeatureBandSearchSymbolFields.PatchVersion, value); + } + } +} diff --git a/src/ext/NetFx/wixext/Symbols/NetFxNetCoreSearchSdkSymbol.cs b/src/ext/NetFx/wixext/Symbols/NetFxNetCoreSearchSdkSymbol.cs index 86b750ea..a368068e 100644 --- a/src/ext/NetFx/wixext/Symbols/NetFxNetCoreSearchSdkSymbol.cs +++ b/src/ext/NetFx/wixext/Symbols/NetFxNetCoreSearchSdkSymbol.cs @@ -12,9 +12,9 @@ namespace WixToolset.Netfx new[] { new IntermediateFieldDefinition(nameof(NetFxNetCoreSdkSearchSymbolFields.Platform), IntermediateFieldType.Number), - new IntermediateFieldDefinition(nameof(NetFxNetCoreSdkSearchSymbolFields.Version), IntermediateFieldType.String), + new IntermediateFieldDefinition(nameof(NetFxNetCoreSdkSearchSymbolFields.MajorVersion), IntermediateFieldType.Number), }, - typeof(NetFxNetCoreSearchSymbol)); + typeof(NetFxNetCoreSdkSearchSymbol)); } } @@ -22,21 +22,12 @@ namespace WixToolset.Netfx.Symbols { using WixToolset.Data; - - public enum NetCoreSdkSearchPlatform - { - X86, - X64, - Arm64, - } - public enum NetFxNetCoreSdkSearchSymbolFields { Platform, - Version, + MajorVersion, } - public class NetFxNetCoreSdkSearchSymbol : IntermediateSymbol { public NetFxNetCoreSdkSearchSymbol() : base(NetfxSymbolDefinitions.NetFxNetCoreSdkSearch, null, null) @@ -49,16 +40,16 @@ namespace WixToolset.Netfx.Symbols public IntermediateField this[NetFxNetCoreSdkSearchSymbolFields index] => this.Fields[(int)index]; - public NetCoreSdkSearchPlatform Platform + public NetCoreSearchPlatform Platform { - get => (NetCoreSdkSearchPlatform)this.Fields[(int)NetFxNetCoreSdkSearchSymbolFields.Platform].AsNumber(); + get => (NetCoreSearchPlatform)this.Fields[(int)NetFxNetCoreSdkSearchSymbolFields.Platform].AsNumber(); set => this.Set((int)NetFxNetCoreSdkSearchSymbolFields.Platform, (int)value); } - public string Version + public int MajorVersion { - get => this.Fields[(int)NetFxNetCoreSdkSearchSymbolFields.Version].AsString(); - set => this.Set((int)NetFxNetCoreSdkSearchSymbolFields.Version, value); + get => this.Fields[(int)NetFxNetCoreSdkSearchSymbolFields.MajorVersion].AsNumber(); + set => this.Set((int)NetFxNetCoreSdkSearchSymbolFields.MajorVersion, value); } } } diff --git a/src/ext/NetFx/wixext/Symbols/NetfxSymbolDefinitions.cs b/src/ext/NetFx/wixext/Symbols/NetfxSymbolDefinitions.cs index 00c52f9e..1db4f647 100644 --- a/src/ext/NetFx/wixext/Symbols/NetfxSymbolDefinitions.cs +++ b/src/ext/NetFx/wixext/Symbols/NetfxSymbolDefinitions.cs @@ -10,8 +10,9 @@ namespace WixToolset.Netfx { NetFxNativeImage, NetFxNetCoreSearch, - NetFxNetCoreSdkSearch, NetFxDotNetCompatibilityCheck, + NetFxNetCoreSdkSearch, + NetFxNetCoreSdkFeatureBandSearch, } public static partial class NetfxSymbolDefinitions @@ -41,6 +42,9 @@ namespace WixToolset.Netfx case NetfxSymbolDefinitionType.NetFxNetCoreSdkSearch: return NetfxSymbolDefinitions.NetFxNetCoreSdkSearch; + case NetfxSymbolDefinitionType.NetFxNetCoreSdkFeatureBandSearch: + return NetfxSymbolDefinitions.NetFxNetCoreSdkFeatureBandSearch; + case NetfxSymbolDefinitionType.NetFxDotNetCompatibilityCheck: return NetfxSymbolDefinitions.NetFxDotNetCompatibilityCheck; @@ -53,6 +57,7 @@ namespace WixToolset.Netfx { NetFxNetCoreSearch.AddTag(BurnConstants.BundleExtensionSearchSymbolDefinitionTag); NetFxNetCoreSdkSearch.AddTag(BurnConstants.BundleExtensionSearchSymbolDefinitionTag); + NetFxNetCoreSdkFeatureBandSearch.AddTag(BurnConstants.BundleExtensionSearchSymbolDefinitionTag); } } } diff --git a/src/test/burn/TestData/TestBA/TestBAWixlib/NetCore6.0.9_x86.wxs b/src/test/burn/TestData/TestBA/TestBAWixlib/NetCore6.0.9_x86.wxs index c2232674..5840bf61 100644 --- a/src/test/burn/TestData/TestBA/TestBAWixlib/NetCore6.0.9_x86.wxs +++ b/src/test/burn/TestData/TestBA/TestBAWixlib/NetCore6.0.9_x86.wxs @@ -5,7 +5,7 @@ - + @@ -61,16 +61,21 @@ - + + + + + + - - - - + + + + - - + + diff --git a/src/test/burn/TestData/TestBA/TestBAWixlib/NetCore6_Platform.wxi b/src/test/burn/TestData/TestBA/TestBAWixlib/NetCore6_Platform.wxi index 8f084b43..c09c3624 100644 --- a/src/test/burn/TestData/TestBA/TestBAWixlib/NetCore6_Platform.wxi +++ b/src/test/burn/TestData/TestBA/TestBAWixlib/NetCore6_Platform.wxi @@ -21,9 +21,10 @@ - - - + + + + diff --git a/src/test/burn/TestData/TestBA/TestBAWixlib_x64/NetCore6.0.9_x64.wxs b/src/test/burn/TestData/TestBA/TestBAWixlib_x64/NetCore6.0.9_x64.wxs index e9ccdc51..0bf4cb35 100644 --- a/src/test/burn/TestData/TestBA/TestBAWixlib_x64/NetCore6.0.9_x64.wxs +++ b/src/test/burn/TestData/TestBA/TestBAWixlib_x64/NetCore6.0.9_x64.wxs @@ -5,7 +5,7 @@ - + @@ -61,16 +61,21 @@ - + + + + + + - - - - + + + + - - + + diff --git a/src/test/burn/TestData/TestBA/TestBAWixlib_x64/WixBA_x64.wxs b/src/test/burn/TestData/TestBA/TestBAWixlib_x64/WixBA_x64.wxs index 6cfbc937..e9cd9827 100644 --- a/src/test/burn/TestData/TestBA/TestBAWixlib_x64/WixBA_x64.wxs +++ b/src/test/burn/TestData/TestBA/TestBAWixlib_x64/WixBA_x64.wxs @@ -1,5 +1,5 @@ - - + + @@ -14,5 +14,7 @@ + + -- cgit v1.2.3-55-g6feb