@@ -61,6 +61,8 @@ IAssemblyCache : public IUnknown
61
61
62
62
typedef HRESULT (__stdcall *LoadLibraryShimFunc)(LPCWSTR szDllName, LPCWSTR szVersion, LPVOID pvReserved, HMODULE *phModDll);
63
63
typedef HRESULT (__stdcall *CreateAssemblyCacheFunc)(IAssemblyCache **ppAsmCache, DWORD dwReserved);
64
+ typedef HRESULT (__stdcall *GetFileVersionFnPtr)(LPCWSTR szFilename, _Out_writes_to_opt_(cchBuffer, *dwLength) LPWSTR szBuffer, DWORD cchBuffer, DWORD* dwLength);
65
+ typedef HRESULT (__stdcall *CorBindToRuntimeExFnPtr)(LPCWSTR pwszVersion, LPCWSTR pwszBuildFlavor, DWORD startupFlags, REFCLSID rclsid, REFIID riid, LPVOID FAR* ppv);
64
66
65
67
66
68
// RegistrationHelper related declarations
@@ -152,7 +154,8 @@ static HRESULT UnregisterAssembly(
152
154
static void InitAssemblyExec ();
153
155
static void UninitAssemblyExec ();
154
156
static HRESULT GetRegistrationHelper (
155
- IDispatch** ppiRegHlp
157
+ IDispatch** ppiRegHlp,
158
+ LPCWSTR pwzAssemblyPath
156
159
);
157
160
static HRESULT GetAssemblyCacheObject (
158
161
IAssemblyCache** ppAssemblyCache
@@ -718,20 +721,44 @@ static void UninitAssemblyExec()
718
721
}
719
722
720
723
static HRESULT GetRegistrationHelper (
721
- IDispatch** ppiRegHlp
724
+ IDispatch** ppiRegHlp,
725
+ LPCWSTR pwzAssemblyPath
722
726
)
723
727
{
724
728
HRESULT hr = S_OK;
729
+ wchar_t pwzVersion[MAX_PATH];
730
+ DWORD pcchVersionLen = MAX_PATH;
731
+ ICLRRuntimeHost* runtimeHost = NULL ;
732
+
733
+ if (!ghMscoree)
734
+ {
735
+ ghMscoree = ::LoadLibraryW (L" mscoree.dll" );
736
+ ExitOnNull (ghMscoree, hr, E_FAIL, " Failed to load mscoree.dll" );
737
+ }
738
+ GetFileVersionFnPtr GetFileVersion = (GetFileVersionFnPtr)::GetProcAddress (ghMscoree, " GetFileVersion" );
739
+ ExitOnNull (GetFileVersion, hr, E_FAIL, " Failed to GetProcAddress for 'GetFileVersion' from 'mscoree.dll'" );
740
+ hr = GetFileVersion (pwzAssemblyPath, pwzVersion, pcchVersionLen, &pcchVersionLen);
725
741
726
742
if (!gpiRegHlp)
727
743
{
728
744
CLSID CLSID_RegistrationHelper{};
729
745
hr = ::CLSIDFromProgID (OLESTR (" System.EnterpriseServices.RegistrationHelper" ), &CLSID_RegistrationHelper);
730
746
ExitOnFailure (hr, " Failed to identify CLSID for 'System.EnterpriseServices.RegistrationHelper'" );
747
+
748
+ // NOTE: The 'CoreBindToRuntimeEx' method is DEPRECATED in .NET v4.
749
+ // HOWEVER, we might be running in an earlier context at this point so we don't want to rely upon stuff that is particularly v4 dependent.
750
+ // Even if we are about to try to fire up a v4 runtime.
751
+ // The .NET v4 runtime with STARTUP_LOADER_SAFEMODE flag (to disable version checking of loaded assemblies) is what lets us launch the
752
+ // RegistrationHelper. The v4 RegistrationHelper is able to register both v4 and v3 assemblies however, so if we can get it, we most as well
753
+ // use it.
754
+ CorBindToRuntimeExFnPtr CorBindToRuntimeEx = (CorBindToRuntimeExFnPtr)::GetProcAddress (ghMscoree, " CorBindToRuntimeEx" );
755
+ hr = CorBindToRuntimeEx (L" v4.0.30319" , L" wks" , STARTUP_LOADER_SAFEMODE, CLSID_CLRRuntimeHost, IID_ICLRRuntimeHost, (LPVOID*)&runtimeHost);
756
+ // we ignore the HRESULT here. If it worked, great, we'll use it moving forward. If it didn't work, we'll end up trying to resort to legacy .NET FW
757
+ // when we just try the COM Create below
758
+
731
759
// create registration helper object
732
- // This will fail with Class not registered if only .NET Framework 4.5 is installed, it appears to require
733
- // .NET 3 to get registered into the system correctly.
734
- hr = ::CoCreateInstance (CLSID_RegistrationHelper, NULL , CLSCTX_ALL, IID_IDispatch, (void **)&gpiRegHlp);
760
+ // This will be created in the .NET FW 4 version if we managed to launch it above, or in the .NET FW <4 version based on the COM dispatch otherwise
761
+ hr = ::CoCreateInstance (CLSID_RegistrationHelper, NULL , CLSCTX_ALL, IID_IDispatch, (void **)&gpiRegHlp);
735
762
ExitOnFailure (hr, " Failed to create registration helper object" );
736
763
}
737
764
@@ -884,7 +911,7 @@ static HRESULT RegisterDotNetAssembly(
884
911
}
885
912
886
913
// get registration helper object
887
- hr = GetRegistrationHelper (&piRegHlp);
914
+ hr = GetRegistrationHelper (&piRegHlp, pAttrs-> pwzDllPath );
888
915
ExitOnFailure (hr, " Failed to get registration helper object" );
889
916
890
917
// get dispatch id of InstallAssembly() method
@@ -1090,7 +1117,7 @@ static HRESULT UnregisterDotNetAssembly(
1090
1117
ExitOnNull (bstrDllPath, hr, E_OUTOFMEMORY, " Failed to allocate BSTR for dll path" );
1091
1118
1092
1119
// get registration helper object
1093
- hr = GetRegistrationHelper (&piRegHlp);
1120
+ hr = GetRegistrationHelper (&piRegHlp, pAttrs-> pwzDllPath );
1094
1121
ExitOnFailure (hr, " Failed to get registration helper object" );
1095
1122
1096
1123
// get dispatch id of UninstallAssembly() method
0 commit comments