aboutsummaryrefslogtreecommitdiff
path: root/src/ext/NetFx/netcoresearch
diff options
context:
space:
mode:
authorSean Hall <r.sean.hall@gmail.com>2023-01-15 19:17:29 -0600
committerSean Hall <r.sean.hall@gmail.com>2023-01-18 18:10:56 -0600
commitd180bc6df297422f189ffd08a0dd558bfbeba1ca (patch)
tree9eac5847ce2335548232480b0ccb197f5dda23a0 /src/ext/NetFx/netcoresearch
parent853887b4e84df1965794802b7683f3a9aca3e930 (diff)
downloadwix-d180bc6df297422f189ffd08a0dd558bfbeba1ca.tar.gz
wix-d180bc6df297422f189ffd08a0dd558bfbeba1ca.tar.bz2
wix-d180bc6df297422f189ffd08a0dd558bfbeba1ca.zip
Add netfx:DotNetCoreSdkFeatureBandSearch.
7058
Diffstat (limited to 'src/ext/NetFx/netcoresearch')
-rw-r--r--src/ext/NetFx/netcoresearch/netcoresearch.cpp327
1 files changed, 189 insertions, 138 deletions
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 @@
2 2
3#include "precomp.h" 3#include "precomp.h"
4 4
5enum class NETCORESEARCHKIND 5enum class NETCORESEARCHTYPE
6{ 6{
7 None, 7 None,
8 Runtime, 8 Runtime,
9 Sdk, 9 Sdk,
10 SdkFeatureBand,
10}; 11};
11 12
12struct NETCORESEARCH_STATE 13struct NETCORESEARCH_STATE
13{ 14{
14 NETCORESEARCHKIND Kind = NETCORESEARCHKIND::None; 15 NETCORESEARCHTYPE type;
15 union 16 HRESULT hrSearch;
16 {
17 struct
18 {
19 LPCWSTR wzTargetName;
20 DWORD dwMajorVersion;
21 } Runtime;
22 struct
23 {
24 DWORD dwMajorVersion;
25 DWORD dwMinorVersion;
26 DWORD dwFeatureBand;
27 }
28 Sdk;
29 } Data;
30 VERUTIL_VERSION* pVersion; 17 VERUTIL_VERSION* pVersion;
18
19 struct
20 {
21 LPCWSTR wzTargetName;
22 DWORD dwMajorVersion;
23 } Runtime;
24 struct
25 {
26 DWORD dwMajorVersion;
27 } Sdk;
28 struct
29 {
30 DWORD dwMajorVersion;
31 DWORD dwMinorVersion;
32 DWORD dwPatchVersion;
33 } SdkFeatureBand;
31}; 34};
32 35
36static HRESULT GetSearchStateFromArguments(
37 __in int argc,
38 __in LPWSTR argv[],
39 __in NETCORESEARCH_STATE* pSearchState
40 );
33static HRESULT GetDotnetEnvironmentInfo( 41static HRESULT GetDotnetEnvironmentInfo(
34 __in NETCORESEARCH_STATE& pSearchState, 42 __in NETCORESEARCH_STATE* pSearchState
35 __inout VERUTIL_VERSION** ppVersion
36 ); 43 );
37static void HOSTFXR_CALLTYPE GetDotnetEnvironmentInfoResult( 44static void HOSTFXR_CALLTYPE GetDotnetEnvironmentInfoResult(
38 __in const hostfxr_dotnet_environment_info* pInfo, 45 __in const hostfxr_dotnet_environment_info* pInfo,
39 __in LPVOID pvContext 46 __in LPVOID pvContext
40 ); 47 );
41 48
42bool string_equal_invariant(__in PCWSTR const x,__in PCWSTR const y) { return CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, x, -1, y, -1); }
43
44HRESULT get_search_state_from_arguments(__in int argc, __in LPWSTR argv[], __out NETCORESEARCH_STATE& searchState);
45
46int __cdecl wmain(int argc, LPWSTR argv[]) 49int __cdecl wmain(int argc, LPWSTR argv[])
47{ 50{
48 HRESULT hr = S_OK; 51 HRESULT hr = S_OK;
49 VERUTIL_VERSION* pVersion = NULL; 52 NETCORESEARCH_STATE searchState = { };
50 NETCORESEARCH_STATE searchState = {};
51
52 ::SetConsoleCP(CP_UTF8);
53 53
54 ConsoleInitialize(); 54 ConsoleInitialize();
55 55
56 hr = get_search_state_from_arguments(argc, argv, OUT searchState); 56 hr = GetSearchStateFromArguments(argc, argv, &searchState);
57 if (FAILED(hr)) 57 ConsoleExitOnFailure(hr, CONSOLE_COLOR_RED, "Failed to parse arguments.");
58 {
59 ConsoleExitOnFailure(hr, CONSOLE_COLOR_RED, "Failed to parse arguments.");
60 }
61 58
62 hr = GetDotnetEnvironmentInfo(searchState, &pVersion); 59 hr = GetDotnetEnvironmentInfo(&searchState);
60 ConsoleExitOnFailure(hr, CONSOLE_COLOR_RED, "Failed to search.");
63 61
64 62 if (searchState.pVersion)
65 if (pVersion)
66 { 63 {
67 ConsoleWriteW(CONSOLE_COLOR_NORMAL, pVersion->sczVersion); 64 ConsoleWriteW(CONSOLE_COLOR_NORMAL, searchState.pVersion->sczVersion);
68 } 65 }
69 66
70LExit: 67LExit:
71 ReleaseVerutilVersion(pVersion); 68 ReleaseVerutilVersion(searchState.pVersion);
72 ConsoleUninitialize(); 69 ConsoleUninitialize();
73 return hr; 70 return hr;
74} 71}
75 72
76HRESULT get_search_state_from_arguments(int argc, LPWSTR argv[], __out NETCORESEARCH_STATE& searchState) 73HRESULT GetSearchStateFromArguments(
74 __in int argc,
75 __in LPWSTR argv[],
76 __in NETCORESEARCH_STATE* pSearchState
77 )
77{ 78{
78 HRESULT hr = S_OK; 79 HRESULT hr = S_OK;
79 searchState = {}; 80 LPCWSTR wzSearchKind = NULL;
80 const auto searchKind = argv[1];
81 81
82 if (argc < 3) 82 if (argc < 2)
83 { 83 {
84 ExitFunction1(hr = E_INVALIDARG); 84 ExitFunction1(hr = E_INVALIDARG);
85 } 85 }
86 86
87 wzSearchKind = argv[1];
87 88
88 if (string_equal_invariant(searchKind, L"runtime")) 89 if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, wzSearchKind, -1, L"runtime", -1))
89 { 90 {
90 if (argc != 4) 91 if (argc != 4)
91 { 92 {
92 ExitFunction1(hr = E_INVALIDARG); 93 ExitFunction1(hr = E_INVALIDARG);
93 } 94 }
94 searchState.Kind = NETCORESEARCHKIND::Runtime;
95 95
96 const PCWSTR majorVersion = argv[2]; 96 LPCWSTR wzMajorVersion = argv[2];
97 const PCWSTR targetName = argv[3]; 97 LPCWSTR wzTargetName = argv[3];
98 98
99 auto& data = searchState.Data.Runtime; 99 pSearchState->type = NETCORESEARCHTYPE::Runtime;
100 100
101 data.wzTargetName = targetName; 101 hr = StrStringToUInt32(wzMajorVersion, 0, reinterpret_cast<UINT*>(&pSearchState->Runtime.dwMajorVersion));
102 hr = StrStringToUInt32(majorVersion, 0, reinterpret_cast<UINT*>(&data.dwMajorVersion)); 102 ConsoleExitOnFailure(hr, CONSOLE_COLOR_RED, "Failed to get target version from: %ls", wzMajorVersion);
103 ConsoleExitOnFailure(hr, CONSOLE_COLOR_RED, "Failed to get target version from: %ls", majorVersion); 103
104 pSearchState->Runtime.wzTargetName = wzTargetName;
104 } 105 }
105 else if(string_equal_invariant(searchKind, L"sdk")) 106 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, wzSearchKind, -1, L"sdk", -1))
106 { 107 {
107 searchState.Kind = NETCORESEARCHKIND::Sdk; 108 if (argc != 3)
109 {
110 ExitFunction1(hr = E_INVALIDARG);
111 }
112
113 LPCWSTR wzMajorVersion = argv[2];
108 114
109 const PCWSTR version = argv[2]; 115 pSearchState->type = NETCORESEARCHTYPE::Sdk;
110 116
111 VERUTIL_VERSION* sdkVersion = nullptr; 117 hr = StrStringToUInt32(wzMajorVersion, 0, reinterpret_cast<UINT*>(&pSearchState->Sdk.dwMajorVersion));
112 hr = VerParseVersion(version, 0, FALSE, &sdkVersion); 118 ConsoleExitOnFailure(hr, CONSOLE_COLOR_RED, "Failed to get sdk major version from: %ls", wzMajorVersion);
113 if (FAILED(hr)) 119 }
120 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, wzSearchKind, -1, L"sdkfeatureband", -1))
121 {
122 if (argc != 5)
114 { 123 {
115 ConsoleExitOnFailure(hr, CONSOLE_COLOR_RED, "Failed to parse version from: %ls", version); 124 ExitFunction1(hr = E_INVALIDARG);
116 } 125 }
117 126
118 auto& data = searchState.Data.Sdk; 127 LPCWSTR wzMajorVersion = argv[2];
128 LPCWSTR wzMinorVersion = argv[3];
129 LPCWSTR wzPatchVersion = argv[4];
130
131 pSearchState->type = NETCORESEARCHTYPE::SdkFeatureBand;
119 132
120 data.dwMajorVersion = sdkVersion->dwMajor; 133 hr = StrStringToUInt32(wzMajorVersion, 0, reinterpret_cast<UINT*>(&pSearchState->SdkFeatureBand.dwMajorVersion));
121 data.dwMinorVersion = sdkVersion->dwMinor; 134 ConsoleExitOnFailure(hr, CONSOLE_COLOR_RED, "Failed to get major version from: %ls", wzMajorVersion);
122 data.dwFeatureBand = sdkVersion->dwPatch;
123 135
124 VerFreeVersion(sdkVersion); 136 hr = StrStringToUInt32(wzMinorVersion, 0, reinterpret_cast<UINT*>(&pSearchState->SdkFeatureBand.dwMinorVersion));
137 ConsoleExitOnFailure(hr, CONSOLE_COLOR_RED, "Failed to get minor version from: %ls", wzMinorVersion);
138
139 hr = StrStringToUInt32(wzPatchVersion, 0, reinterpret_cast<UINT*>(&pSearchState->SdkFeatureBand.dwPatchVersion));
140 ConsoleExitOnFailure(hr, CONSOLE_COLOR_RED, "Failed to get patch version from: %ls", wzPatchVersion);
141 }
142 else
143 {
144 pSearchState->type = NETCORESEARCHTYPE::None;
145 ExitFunction1(hr = E_INVALIDARG);
125 } 146 }
126 147
127LExit: 148LExit:
128 return hr; 149 return hr;
129} 150}
130 151
131
132
133static HRESULT GetDotnetEnvironmentInfo( 152static HRESULT GetDotnetEnvironmentInfo(
134 __in NETCORESEARCH_STATE& state, 153 __in NETCORESEARCH_STATE* pState
135 __inout VERUTIL_VERSION** ppVersion
136 ) 154 )
137{ 155{
138 HRESULT hr = S_OK; 156 HRESULT hr = S_OK;
@@ -156,17 +174,13 @@ static HRESULT GetDotnetEnvironmentInfo(
156 pfnGetDotnetEnvironmentInfo = (hostfxr_get_dotnet_environment_info_fn)::GetProcAddress(hModule, "hostfxr_get_dotnet_environment_info"); 174 pfnGetDotnetEnvironmentInfo = (hostfxr_get_dotnet_environment_info_fn)::GetProcAddress(hModule, "hostfxr_get_dotnet_environment_info");
157 ConsoleExitOnNullWithLastError(pfnGetDotnetEnvironmentInfo, hr, CONSOLE_COLOR_RED, "Failed to get address for hostfxr_get_dotnet_environment_info."); 175 ConsoleExitOnNullWithLastError(pfnGetDotnetEnvironmentInfo, hr, CONSOLE_COLOR_RED, "Failed to get address for hostfxr_get_dotnet_environment_info.");
158 176
159 hr = pfnGetDotnetEnvironmentInfo(NULL, NULL, GetDotnetEnvironmentInfoResult, &state); 177 hr = pfnGetDotnetEnvironmentInfo(NULL, NULL, GetDotnetEnvironmentInfoResult, pState);
160 ConsoleExitOnFailure(hr, CONSOLE_COLOR_RED, "Failed to get .NET Core environment info."); 178 ConsoleExitOnFailure(hr, CONSOLE_COLOR_RED, "Failed to get .NET Core environment info.");
161 179
162 if (state.pVersion) 180 hr = pState->hrSearch;
163 { 181 ConsoleExitOnFailure(hr, CONSOLE_COLOR_RED, "Failed to process .NET Core environment info.");
164 *ppVersion = state.pVersion;
165 state.pVersion = NULL;
166 }
167 182
168LExit: 183LExit:
169 ReleaseVerutilVersion(state.pVersion);
170 ReleaseStr(sczHostfxrPath); 184 ReleaseStr(sczHostfxrPath);
171 ReleaseStr(sczProcessPath); 185 ReleaseStr(sczProcessPath);
172 186
@@ -178,108 +192,145 @@ LExit:
178 return hr; 192 return hr;
179} 193}
180 194
181bool matches_feature_band(const int requested, const int actual) 195static HRESULT PerformRuntimeSearch(
196 __in const hostfxr_dotnet_environment_info* pInfo,
197 __in DWORD dwMajorVersion,
198 __in LPCWSTR wzTargetName,
199 __inout VERUTIL_VERSION** ppVersion
200 )
182{ 201{
183 // we have not requested a match on feature band, so skip the check 202 HRESULT hr = S_OK;
184 if (requested == 0) return true; 203 VERUTIL_VERSION* pFrameworkVersion = NULL;
204 int nCompare = 0;
205
206 for (size_t i = 0; i < pInfo->framework_count; ++i)
207 {
208 const hostfxr_dotnet_environment_framework_info* pFrameworkInfo = pInfo->frameworks + i;
209 ReleaseVerutilVersion(pFrameworkVersion);
210
211 if (CSTR_EQUAL != ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, wzTargetName, -1, pFrameworkInfo->name, -1))
212 {
213 continue;
214 }
215
216 hr = VerParseVersion(pFrameworkInfo->version, 0, FALSE, &pFrameworkVersion);
217 ConsoleExitOnFailure(hr, CONSOLE_COLOR_RED, "Failed to parse framework version: %ls", pFrameworkInfo->version);
218
219 if (pFrameworkVersion->dwMajor != dwMajorVersion)
220 {
221 continue;
222 }
223
224 if (*ppVersion)
225 {
226 hr = VerCompareParsedVersions(*ppVersion, pFrameworkVersion, &nCompare);
227 ConsoleExitOnFailure(hr, CONSOLE_COLOR_RED, "Failed to compare versions.");
185 228
186 const int requestedBand = requested / 100; 229 if (nCompare > -1)
187 const int actualBand = actual / 100; 230 {
231 continue;
232 }
233 }
188 234
189 if (actualBand != requestedBand) return false; 235 ReleaseVerutilVersion(*ppVersion);
236 *ppVersion = pFrameworkVersion;
237 pFrameworkVersion = NULL;
238 }
190 239
191 return actual >= requested; 240LExit:
241 ReleaseVerutilVersion(pFrameworkVersion);
242
243 return hr;
192} 244}
193 245
194static void HOSTFXR_CALLTYPE GetDotnetEnvironmentInfoResult( 246static HRESULT PerformSdkSearch(
195 __in const hostfxr_dotnet_environment_info* pInfo, 247 __in const hostfxr_dotnet_environment_info* pInfo,
196 __in LPVOID pvContext 248 __in BOOL fFeatureBand,
249 __in DWORD dwMajorVersion,
250 __in DWORD dwMinorVersion,
251 __in DWORD dwPatchVersion,
252 __inout VERUTIL_VERSION** ppVersion
197 ) 253 )
198{ 254{
199 NETCORESEARCH_STATE* pState = static_cast<NETCORESEARCH_STATE*>(pvContext);
200 HRESULT hr = S_OK; 255 HRESULT hr = S_OK;
201 VERUTIL_VERSION* pDotnetVersion = nullptr; 256 VERUTIL_VERSION* pSdkVersion = NULL;
202 int nCompare = 0; 257 int nCompare = 0;
258 DWORD dwRequestedBand = dwPatchVersion / 100;
203 259
204 260 for (size_t i = 0; i < pInfo->sdk_count; ++i)
205 if (pState->Kind == NETCORESEARCHKIND::Sdk)
206 { 261 {
207 auto& sdkData = pState->Data.Sdk; 262 const hostfxr_dotnet_environment_sdk_info* pSdkInfo = pInfo->sdks + i;
208 for (size_t i = 0; i < pInfo->sdk_count; ++i) 263 ReleaseVerutilVersion(pSdkVersion);
209 {
210 const hostfxr_dotnet_environment_sdk_info* pSdkInfo = pInfo->sdks + i;
211 ReleaseVerutilVersion(pDotnetVersion);
212 264
213 hr = VerParseVersion(pSdkInfo->version, 0, FALSE, &pDotnetVersion); 265 hr = VerParseVersion(pSdkInfo->version, 0, FALSE, &pSdkVersion);
214 ConsoleExitOnFailure(hr, CONSOLE_COLOR_RED, "Failed to parse sdk version: %ls", pSdkInfo->version); 266 ConsoleExitOnFailure(hr, CONSOLE_COLOR_RED, "Failed to parse sdk version: %ls", pSdkInfo->version);
215 267
216 if (pDotnetVersion->dwMajor != sdkData.dwMajorVersion) 268 if (pSdkVersion->dwMajor != dwMajorVersion)
217 { 269 {
218 continue; 270 continue;
219 } 271 }
220 if (!matches_feature_band(sdkData.dwFeatureBand, pDotnetVersion->dwPatch)) 272
273 if (fFeatureBand)
274 {
275 if (pSdkVersion->dwMinor != dwMinorVersion)
221 { 276 {
222 continue; 277 continue;
223 } 278 }
224 279
225 if (pState->pVersion) 280 if ((pSdkVersion->dwPatch / 100) != dwRequestedBand)
226 { 281 {
227 hr = VerCompareParsedVersions(pState->pVersion, pDotnetVersion, &nCompare); 282 continue;
228 ConsoleExitOnFailure(hr, CONSOLE_COLOR_RED, "Failed to compare versions.");
229
230 if (nCompare > -1)
231 {
232 continue;
233 }
234 } 283 }
235
236 ReleaseVerutilVersion(pState->pVersion);
237 pState->pVersion = pDotnetVersion;
238 pDotnetVersion = nullptr;
239 } 284 }
240 } 285
241 else if(pState->Kind == NETCORESEARCHKIND::Runtime) 286 if (*ppVersion)
242 {
243 auto& runtimeData = pState->Data.Runtime;
244 for (size_t i = 0; i < pInfo->framework_count; ++i)
245 { 287 {
246 const hostfxr_dotnet_environment_framework_info* pFrameworkInfo = pInfo->frameworks + i; 288 hr = VerCompareParsedVersions(*ppVersion, pSdkVersion, &nCompare);
247 ReleaseVerutilVersion(pDotnetVersion); 289 ConsoleExitOnFailure(hr, CONSOLE_COLOR_RED, "Failed to compare versions.");
248 290
249 if (string_equal_invariant(runtimeData.wzTargetName, pFrameworkInfo->name)) 291 if (nCompare > -1)
250 { 292 {
251 continue; 293 continue;
252 } 294 }
295 }
253 296
254 hr = VerParseVersion(pFrameworkInfo->version, 0, FALSE, &pDotnetVersion); 297 ReleaseVerutilVersion(*ppVersion);
255 ConsoleExitOnFailure(hr, CONSOLE_COLOR_RED, "Failed to parse framework version: %ls", pFrameworkInfo->version); 298 *ppVersion = pSdkVersion;
299 pSdkVersion = NULL;
300 }
256 301
257 if (pDotnetVersion->dwMajor != runtimeData.dwMajorVersion) 302LExit:
258 { 303 ReleaseVerutilVersion(pSdkVersion);
259 continue;
260 }
261 304
262 if (pState->pVersion) 305 return hr;
263 { 306}
264 hr = VerCompareParsedVersions(pState->pVersion, pDotnetVersion, &nCompare);
265 ConsoleExitOnFailure(hr, CONSOLE_COLOR_RED, "Failed to compare versions.");
266 307
267 if (nCompare > -1) 308static void HOSTFXR_CALLTYPE GetDotnetEnvironmentInfoResult(
268 { 309 __in const hostfxr_dotnet_environment_info* pInfo,
269 continue; 310 __in LPVOID pvContext
270 } 311 )
271 } 312{
313 NETCORESEARCH_STATE* pState = static_cast<NETCORESEARCH_STATE*>(pvContext);
314 HRESULT hr = S_OK;
272 315
273 ReleaseVerutilVersion(pState->pVersion); 316 if (pState->type == NETCORESEARCHTYPE::Sdk)
274 pState->pVersion = pDotnetVersion; 317 {
275 pDotnetVersion = nullptr; 318 hr = PerformSdkSearch(pInfo, FALSE, pState->Sdk.dwMajorVersion, 0, 0, &pState->pVersion);
276 } 319 }
320 else if (pState->type == NETCORESEARCHTYPE::SdkFeatureBand)
321 {
322 hr = PerformSdkSearch(pInfo, TRUE, pState->SdkFeatureBand.dwMajorVersion, pState->SdkFeatureBand.dwMinorVersion, pState->SdkFeatureBand.dwPatchVersion, &pState->pVersion);
323 }
324 else if (pState->type == NETCORESEARCHTYPE::Runtime)
325 {
326 hr = PerformRuntimeSearch(pInfo, pState->Runtime.dwMajorVersion, pState->Runtime.wzTargetName, &pState->pVersion);
277 } 327 }
278 else 328 else
279 { 329 {
280 ConsoleWriteError(E_INVALIDARG, CONSOLE_COLOR_RED, "Invalid NETCORESEARCHKIND."); 330 hr = E_INVALIDARG;
331 ConsoleExitOnFailure(hr, CONSOLE_COLOR_RED, "Invalid NETCORESEARCHTYPE.");
281 } 332 }
282 333
283LExit: 334LExit:
284 ReleaseVerutilVersion(pDotnetVersion); 335 pState->hrSearch = hr;
285} 336}