Skip to content

Commit ee40cae

Browse files
committed
Fix #55847: DOTNET .NET 4.0 GAC new location
If we do not specify the exact version of the .NET framework to use, the default CLR is loaded, which is typically CLR 2, which is very old. Therefore, we introduce a `PHP_INI_SYSTEM` setting, which allows users to choose the desired .NET framework version. The value of the setting are the first three parts of the framework's version number, separated by dots, and prefixed with "v", e.g. "v4.0.30319". If the value of the INI setting is `NULL` (the default) or an empty string, the default CLR is used. Internally, we switch from the most generic `CoCreateInstance()` to `CorBindToRuntime()` which is implemented in mscoree.dll. To avoid the hard dependency to that library, we load dynamically. So this fix is supposed to be fully backwards compatible.
1 parent a35379d commit ee40cae

File tree

4 files changed

+49
-4
lines changed

4 files changed

+49
-4
lines changed

ext/com_dotnet/com_dotnet.c

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,44 @@ struct dotnet_runtime_stuff {
119119
DISPID create_instance;
120120
};
121121

122+
/* We link dynamically to mscoree.dll to avoid the hard dependency on .NET
123+
* framework, which is only required if a dotnet instance is to be created.
124+
*/
125+
static HRESULT dotnet_bind_runtime(LPVOID FAR *ppv)
126+
{
127+
HRESULT hr;
128+
HMODULE mscoree;
129+
typedef HRESULT (STDAPICALLTYPE *cbtr_t)(LPCWSTR pwszVersion, LPCWSTR pwszBuildFlavor, REFCLSID rclsid, REFIID riid, LPVOID FAR *ppv);
130+
cbtr_t CorBindToRuntime;
131+
OLECHAR *oleversion;
132+
char *version;
133+
134+
mscoree = LoadLibraryA("mscoree.dll");
135+
if (mscoree == NULL) {
136+
return S_FALSE;
137+
}
138+
139+
CorBindToRuntime = (cbtr_t) GetProcAddress(mscoree, "CorBindToRuntime");
140+
if (CorBindToRuntime == NULL) {
141+
FreeLibrary(mscoree);
142+
return S_FALSE;
143+
}
144+
145+
version = INI_STR("com.dotnet_version");
146+
if (version == NULL || *version == '\0') {
147+
oleversion = NULL;
148+
} else {
149+
oleversion = php_com_string_to_olestring(version, strlen(version), COMG(code_page));
150+
}
151+
152+
hr = CorBindToRuntime(oleversion, NULL, &CLSID_CorRuntimeHost, &IID_ICorRuntimeHost, ppv);
153+
154+
efree(oleversion);
155+
FreeLibrary(mscoree);
156+
157+
return hr;
158+
}
159+
122160
static HRESULT dotnet_init(char **p_where)
123161
{
124162
HRESULT hr;
@@ -132,10 +170,8 @@ static HRESULT dotnet_init(char **p_where)
132170
}
133171
memset(stuff, 0, sizeof(*stuff));
134172

135-
where = "CoCreateInstance";
136-
hr = CoCreateInstance(&CLSID_CorRuntimeHost, NULL, CLSCTX_ALL,
137-
&IID_ICorRuntimeHost, (LPVOID*)&stuff->dotnet_host);
138-
173+
where = "dotnet_bind_runtime";
174+
hr = dotnet_bind_runtime((LPVOID*)&stuff->dotnet_host);
139175
if (FAILED(hr))
140176
goto out;
141177

ext/com_dotnet/com_extension.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,7 @@ PHP_INI_BEGIN()
279279
STD_PHP_INI_ENTRY("com.autoregister_casesensitive", "1", PHP_INI_ALL, OnAutoregisterCasesensitive, autoreg_case_sensitive, zend_com_dotnet_globals, com_dotnet_globals)
280280
STD_PHP_INI_ENTRY("com.code_page", "", PHP_INI_ALL, OnUpdateLong, code_page, zend_com_dotnet_globals, com_dotnet_globals)
281281
PHP_INI_ENTRY("com.typelib_file", "", PHP_INI_SYSTEM, OnTypeLibFileUpdate)
282+
PHP_INI_ENTRY("com.dotnet_version", NULL, PHP_INI_SYSTEM, NULL)
282283
PHP_INI_END()
283284
/* }}} */
284285

php.ini-development

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1613,6 +1613,10 @@ zend.assertions = 1
16131613
; Default: system ANSI code page
16141614
;com.code_page=
16151615

1616+
; The version of the .NET framework to use. The value of the setting are the first three parts
1617+
; of the framework's version number, separated by dots, and prefixed with "v", e.g. "v4.0.30319".
1618+
;com.dotnet_version=
1619+
16161620
[mbstring]
16171621
; language for internal character representation.
16181622
; This affects mb_send_mail() and mbstring.detect_order.

php.ini-production

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1615,6 +1615,10 @@ zend.assertions = -1
16151615
; Default: system ANSI code page
16161616
;com.code_page=
16171617

1618+
; The version of the .NET framework to use. The value of the setting are the first three parts
1619+
; of the framework's version number, separated by dots, and prefixed with "v", e.g. "v4.0.30319".
1620+
;com.dotnet_version=
1621+
16181622
[mbstring]
16191623
; language for internal character representation.
16201624
; This affects mb_send_mail() and mbstring.detect_order.

0 commit comments

Comments
 (0)