Skip to content

Commit e6044d4

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. Closes phpGH-5949
1 parent 969a432 commit e6044d4

File tree

6 files changed

+56
-4
lines changed

6 files changed

+56
-4
lines changed

NEWS

+3
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ PHP NEWS
66
. Fixed bug #80007 (Potential type confusion in unixtojd() parameter parsing).
77
(Andy Postnikov)
88

9+
- COM:
10+
. Fixed bug #55847 (DOTNET .NET 4.0 GAC new location). (cmb)
11+
912
- DOM:
1013
. Fixed bug #79968 (DOMChildNode API crash on unattached nodes). (Benjamin)
1114

UPGRADING

+4
Original file line numberDiff line numberDiff line change
@@ -1048,6 +1048,10 @@ PHP 8.0 UPGRADE NOTES
10481048
. New INI directive to set the maximum string length in an argument of a
10491049
stringified stack strace.
10501050

1051+
- com.dotnet_version
1052+
. New INI directive to choose the version of the .NET framework to use for
1053+
dotnet objects.
1054+
10511055
========================================
10521056
12. Windows Support
10531057
========================================

ext/com_dotnet/com_dotnet.c

+40-4
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,44 @@ struct dotnet_runtime_stuff {
117117
DISPID create_instance;
118118
};
119119

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

133-
where = "CoCreateInstance";
134-
hr = CoCreateInstance(&CLSID_CorRuntimeHost, NULL, CLSCTX_ALL,
135-
&IID_ICorRuntimeHost, (LPVOID*)&stuff->dotnet_host);
136-
171+
where = "dotnet_bind_runtime";
172+
hr = dotnet_bind_runtime((LPVOID*)&stuff->dotnet_host);
137173
if (FAILED(hr))
138174
goto out;
139175

ext/com_dotnet/com_extension.c

+1
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@ PHP_INI_BEGIN()
141141
STD_PHP_INI_ENTRY("com.autoregister_casesensitive", "1", PHP_INI_ALL, OnAutoregisterCasesensitive, autoreg_case_sensitive, zend_com_dotnet_globals, com_dotnet_globals)
142142
STD_PHP_INI_ENTRY("com.code_page", "", PHP_INI_ALL, OnUpdateLong, code_page, zend_com_dotnet_globals, com_dotnet_globals)
143143
PHP_INI_ENTRY("com.typelib_file", "", PHP_INI_SYSTEM, OnTypeLibFileUpdate)
144+
PHP_INI_ENTRY("com.dotnet_version", NULL, PHP_INI_SYSTEM, NULL)
144145
PHP_INI_END()
145146
/* }}} */
146147

php.ini-development

+4
Original file line numberDiff line numberDiff line change
@@ -1614,6 +1614,10 @@ zend.assertions = 1
16141614
; Default: system ANSI code page
16151615
;com.code_page=
16161616

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

php.ini-production

+4
Original file line numberDiff line numberDiff line change
@@ -1618,6 +1618,10 @@ zend.assertions = -1
16181618
; Default: system ANSI code page
16191619
;com.code_page=
16201620

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

0 commit comments

Comments
 (0)