summaryrefslogtreecommitdiff
path: root/src/ext/NetFx/ca
diff options
context:
space:
mode:
authorStefanStojanovic <StefanStojanovic@users.noreply.github.com>2022-10-25 22:40:36 +0200
committerGitHub <noreply@github.com>2022-10-25 20:40:36 +0000
commit321c30138c82390ea5ad6b0a612dff294203a877 (patch)
tree2f27ca578d9b162eac11f0c8bee460b17138b531 /src/ext/NetFx/ca
parent98080672cdbbde00ea40a96c1ce38e8a52f24fee (diff)
downloadwix-321c30138c82390ea5ad6b0a612dff294203a877.tar.gz
wix-321c30138c82390ea5ad6b0a612dff294203a877.tar.bz2
wix-321c30138c82390ea5ad6b0a612dff294203a877.zip
Add NetFx .NET compatibility check for MSI (#262)
Adds new custom element in NetFx extension for running NetCoreCheck.exe tool from within the MSI installer - `<netfx:DotNetCompatibilityCheck />`. The checks are run before evaluating launch conditions, so their results can be used in those conditions. There is no limitation on the number of checks that can be run, so installer may query various runtimes on different platforms and versions and with different roll forward policies. Fixes https://github.com/wixtoolset/issues/issues/6264
Diffstat (limited to 'src/ext/NetFx/ca')
-rw-r--r--src/ext/NetFx/ca/netfxca.cpp144
-rw-r--r--src/ext/NetFx/ca/netfxca.def1
-rw-r--r--src/ext/NetFx/ca/netfxca.vcxproj2
-rw-r--r--src/ext/NetFx/ca/precomp.h3
4 files changed, 149 insertions, 1 deletions
diff --git a/src/ext/NetFx/ca/netfxca.cpp b/src/ext/NetFx/ca/netfxca.cpp
index f0704790..cd086c53 100644
--- a/src/ext/NetFx/ca/netfxca.cpp
+++ b/src/ext/NetFx/ca/netfxca.cpp
@@ -36,6 +36,10 @@ LPCWSTR vcsNgenStrongName =
36 L"SELECT `Name`,`Value` FROM `MsiAssemblyName` WHERE `Component_`=?"; 36 L"SELECT `Name`,`Value` FROM `MsiAssemblyName` WHERE `Component_`=?";
37enum eNgenStrongName { ngsnName = 1, ngsnValue }; 37enum eNgenStrongName { ngsnName = 1, ngsnValue };
38 38
39LPCWSTR vscDotNetCompatibilityCheckQuery =
40 L"SELECT `Platform`, `RuntimeType`, `Version`, `RollForward`, `Property` FROM `Wix4NetFxDotNetCheck`";
41enum eDotNetCompatibilityCheckQuery { platform = 1, runtimeType, version, rollForward, property };
42
39// Searches subdirectories of the given path for the highest version of ngen.exe available 43// Searches subdirectories of the given path for the highest version of ngen.exe available
40static HRESULT GetNgenVersion( 44static HRESULT GetNgenVersion(
41 __in LPWSTR pwzParentPath, 45 __in LPWSTR pwzParentPath,
@@ -500,6 +504,15 @@ extern "C" UINT __stdcall SchedNetFx(
500 hr = WcaInitialize(hInstall, "SchedNetFx"); 504 hr = WcaInitialize(hInstall, "SchedNetFx");
501 ExitOnFailure(hr, "failed to initialize"); 505 ExitOnFailure(hr, "failed to initialize");
502 506
507 // If Wix4NetFxNativeImage table doesn't exist skip the rest of this custom action
508 hr = WcaTableExists(L"Wix4NetFxNativeImage");
509 if (S_FALSE == hr)
510 {
511 hr = S_OK;
512 ExitFunction();
513 }
514 ExitOnFailure(hr, "failed to check if table Wix4NetFxNativeImage exists");
515
503 hr = GetNgenPath(&pwz32Ngen, FALSE); 516 hr = GetNgenPath(&pwz32Ngen, FALSE);
504 f32NgenExeExists = SUCCEEDED(hr); 517 f32NgenExeExists = SUCCEEDED(hr);
505 if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr || HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) == hr) 518 if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr || HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) == hr)
@@ -879,3 +892,134 @@ LExit:
879 return WcaFinalize(er); 892 return WcaFinalize(er);
880} 893}
881 894
895/******************************************************************
896 DotNetCompatibilityCheck - entry point for NetFx Custom Action
897
898*******************************************************************/
899extern "C" UINT __stdcall DotNetCompatibilityCheck(
900 __in MSIHANDLE hInstall
901 )
902{
903// AssertSz(FALSE, "debug DotNetCompatibilityCheck");
904
905 HRESULT hr = S_OK;
906 UINT er = ERROR_SUCCESS;
907
908 PMSIHANDLE hView = NULL;
909 PMSIHANDLE hRec = NULL;
910 LPWSTR pwzPlatform = NULL;
911 LPWSTR pwzNetCoreCheckBinaryId = NULL;
912 LPWSTR pwzNetCoreCheckDirectoryName = NULL;
913 LPWSTR pwzNetCoreCheckDirectoryPath = NULL;
914 LPWSTR pwzNetCoreCheckFilePath = NULL;
915 LPWSTR pwzRuntimeType = NULL;
916 LPWSTR pwzVersion = NULL;
917 LPWSTR pwzRollForward = NULL;
918 LPWSTR pwzProperty = NULL;
919 LPWSTR pwzCommandLine = NULL;
920 HANDLE hProcess = NULL;
921 DWORD dwExitCode = 0;
922
923 // Initialize
924 hr = WcaInitialize(hInstall, "DotNetCompatibilityCheck");
925 ExitOnFailure(hr, "failed to initialize");
926
927 // If Wix4NetFxDotNetCheck table doesn't exist skip the rest of this custom action
928 hr = WcaTableExists(L"Wix4NetFxDotNetCheck");
929 if (S_FALSE == hr)
930 {
931 hr = S_OK;
932 ExitFunction();
933 }
934 ExitOnFailure(hr, "failed to check if table Wix4NetFxDotNetCheck exists");
935
936 // Open view on .NET compatibility check table
937 hr = WcaOpenExecuteView(vscDotNetCompatibilityCheckQuery, &hView);
938 ExitOnFailure(hr, "failed to open view on Wix4NetFxDotNetCheck table");
939
940 // Go through all records and run NetCorCheck.exe for each
941 while (S_OK == (hr = WcaFetchRecord(hView, &hRec)))
942 {
943 // Extract NetCoreCheck.exe for platform to temp directory
944 hr = WcaGetRecordString(hRec, platform, &pwzPlatform);
945 ExitOnFailure(hr, "failed to get Wix4NetFxDotNetCheck.Platform");
946
947 hr = StrAllocFormatted(&pwzNetCoreCheckBinaryId, L"Wix4NetCheck_%ls", pwzPlatform);
948 ExitOnFailure(hr, "failed to get NetCoreCheck binary id for platform %ls", pwzPlatform);
949
950 hr = GuidCreate(&pwzNetCoreCheckDirectoryName);
951 ExitOnFailure(hr, "failed to set NetCoreCheck directory name");
952
953 hr = PathCreateTempDirectory(NULL, pwzNetCoreCheckDirectoryName, 1, &pwzNetCoreCheckDirectoryPath);
954 ExitOnFailure(hr, "failed to make NetCoreCheck directory path for name %ls", pwzNetCoreCheckDirectoryName);
955
956 hr = StrAllocFormatted(&pwzNetCoreCheckFilePath, L"%lsNetCoreCheck.exe", pwzNetCoreCheckDirectoryPath);
957 ExitOnFailure(hr, "failed to set NetCoreCheck file path for directory %ls", pwzNetCoreCheckDirectoryPath);
958
959 hr = WcaExtractBinaryToFile(pwzNetCoreCheckBinaryId, pwzNetCoreCheckFilePath);
960 ExitOnFailure(hr, "failed to extract NetCoreCheck from binary '%ls' to file %ls", pwzNetCoreCheckBinaryId, pwzNetCoreCheckFilePath);
961
962 // Read all NetCoreCheck.exe parameters and property
963 hr = WcaGetRecordString(hRec, runtimeType, &pwzRuntimeType);
964 ExitOnFailure(hr, "failed to get Wix4NetFxDotNetCheck.RuntimeType");
965
966 hr = WcaGetRecordString(hRec, version, &pwzVersion);
967 ExitOnFailure(hr, "failed to get Wix4NetFxDotNetCheck.Version");
968
969 hr = WcaGetRecordString(hRec, rollForward, &pwzRollForward);
970 ExitOnFailure(hr, "failed to get Wix4NetFxDotNetCheck.RollForward");
971
972 hr = WcaGetRecordString(hRec, property, &pwzProperty);
973 ExitOnFailure(hr, "failed to get Wix4NetFxDotNetCheck.Property");
974
975 // Run NetCoreCheck.exe and store its result in property
976 hr = StrAllocFormatted(&pwzCommandLine, L"-n %ls -v %ls -r %ls", pwzRuntimeType, pwzVersion, pwzRollForward);
977 ExitOnFailure(hr, "failed to set NetCoreCheck command line");
978 WcaLog(LOGMSG_VERBOSE, "Command: %ls %ls", pwzNetCoreCheckFilePath, pwzCommandLine);
979
980 hr = ProcExec(pwzNetCoreCheckFilePath, pwzCommandLine, SW_HIDE, &hProcess);
981 ExitOnFailure(hr, "failed to run NetCoreCheck from binary '%ls' with command line: %ls %ls", pwzNetCoreCheckBinaryId, pwzNetCoreCheckFilePath, pwzCommandLine);
982
983 hr = ProcWaitForCompletion(hProcess, INFINITE, &dwExitCode);
984 ExitOnFailure(hr, "failed to finish NetCoreCheck from binary '%ls' with command line: %ls %ls", pwzNetCoreCheckBinaryId, pwzNetCoreCheckFilePath, pwzCommandLine);
985 WcaLog(LOGMSG_VERBOSE, "Exit code: %lu", dwExitCode);
986 ReleaseHandle(hProcess);
987
988 hr = WcaSetIntProperty(pwzProperty, dwExitCode);
989 ExitOnFailure(hr, "failed to set NetCoreCheck result in %ls", pwzProperty);
990
991 // Delete extracted NetCoreCheck.exe
992 DirEnsureDelete(pwzNetCoreCheckDirectoryPath, TRUE, TRUE);
993 }
994 if (E_NOMOREITEMS == hr)
995 {
996 hr = S_OK;
997 }
998 ExitOnFailure(hr, "failed while looping through all dot net compatibility checks");
999
1000LExit:
1001 // Delete extracted NetCoreCheck.exe
1002 if (NULL != pwzNetCoreCheckDirectoryPath)
1003 {
1004 DirEnsureDelete(pwzNetCoreCheckDirectoryPath, TRUE, TRUE);
1005 }
1006
1007 // Release allocated resources
1008 ReleaseStr(pwzPlatform);
1009 ReleaseStr(pwzNetCoreCheckBinaryId);
1010 ReleaseStr(pwzNetCoreCheckDirectoryName);
1011 ReleaseStr(pwzNetCoreCheckDirectoryPath);
1012 ReleaseStr(pwzNetCoreCheckFilePath);
1013 ReleaseStr(pwzRuntimeType);
1014 ReleaseStr(pwzVersion);
1015 ReleaseStr(pwzRollForward);
1016 ReleaseStr(pwzProperty);
1017 ReleaseStr(pwzCommandLine);
1018 ReleaseHandle(hProcess);
1019
1020 if (FAILED(hr))
1021 {
1022 er = ERROR_INSTALL_FAILURE;
1023 }
1024 return WcaFinalize(er);
1025}
diff --git a/src/ext/NetFx/ca/netfxca.def b/src/ext/NetFx/ca/netfxca.def
index c1d01f5f..3b930756 100644
--- a/src/ext/NetFx/ca/netfxca.def
+++ b/src/ext/NetFx/ca/netfxca.def
@@ -6,3 +6,4 @@ LIBRARY "netfxca"
6EXPORTS 6EXPORTS
7 SchedNetFx 7 SchedNetFx
8 ExecNetFx 8 ExecNetFx
9 DotNetCompatibilityCheck
diff --git a/src/ext/NetFx/ca/netfxca.vcxproj b/src/ext/NetFx/ca/netfxca.vcxproj
index 93276ea1..0158a656 100644
--- a/src/ext/NetFx/ca/netfxca.vcxproj
+++ b/src/ext/NetFx/ca/netfxca.vcxproj
@@ -42,7 +42,7 @@
42 <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> 42 <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
43 43
44 <PropertyGroup> 44 <PropertyGroup>
45 <ProjectAdditionalLinkLibraries>msi.lib</ProjectAdditionalLinkLibraries> 45 <ProjectAdditionalLinkLibraries>msi.lib;rpcrt4.lib</ProjectAdditionalLinkLibraries>
46 </PropertyGroup> 46 </PropertyGroup>
47 47
48 <ItemGroup> 48 <ItemGroup>
diff --git a/src/ext/NetFx/ca/precomp.h b/src/ext/NetFx/ca/precomp.h
index f7b537ed..db618bce 100644
--- a/src/ext/NetFx/ca/precomp.h
+++ b/src/ext/NetFx/ca/precomp.h
@@ -10,6 +10,9 @@
10#include "fileutil.h" 10#include "fileutil.h"
11#include "strutil.h" 11#include "strutil.h"
12#include "pathutil.h" 12#include "pathutil.h"
13#include "procutil.h"
14#include "dirutil.h"
15#include "guidutil.h"
13 16
14#include "caDecor.h" 17#include "caDecor.h"
15#include "cost.h" 18#include "cost.h"