]> granicus.if.org Git - php/commitdiff
Fix #55847: DOTNET .NET 4.0 GAC new location
authorChristoph M. Becker <cmbecker69@gmx.de>
Thu, 6 Aug 2020 16:57:18 +0000 (18:57 +0200)
committerChristoph M. Becker <cmbecker69@gmx.de>
Sat, 22 Aug 2020 10:42:34 +0000 (12:42 +0200)
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 GH-5949

NEWS
UPGRADING
ext/com_dotnet/com_dotnet.c
ext/com_dotnet/com_extension.c
php.ini-development
php.ini-production

diff --git a/NEWS b/NEWS
index 65395d8f2bb58adc9cb00918b993e7f7db2f546e..8d81c0cd5cc5ac41718680277e53b84e8d5c8dd9 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -6,6 +6,9 @@ PHP                                                                        NEWS
   . Fixed bug #80007 (Potential type confusion in unixtojd() parameter parsing).
     (Andy Postnikov)
 
+- COM:
+  . Fixed bug #55847 (DOTNET .NET 4.0 GAC new location). (cmb)
+
 - DOM:
   . Fixed bug #79968 (DOMChildNode API crash on unattached nodes). (Benjamin)
 
index 9cb89cf9695f5a23b0e2a07732dde6657151c278..2412b60865f5ee4dbc1132fed567bce5237af62a 100644 (file)
--- a/UPGRADING
+++ b/UPGRADING
@@ -1048,6 +1048,10 @@ PHP 8.0 UPGRADE NOTES
   . New INI directive to set the maximum string length in an argument of a
     stringified stack strace.
 
+- com.dotnet_version
+  . New INI directive to choose the version of the .NET framework to use for
+    dotnet objects.
+
 ========================================
 12. Windows Support
 ========================================
index 6bd492ef1d9b924ba4049e117d41bddf1631c849..1b0ba2220c3a005febad96aafd00364242ba8ac2 100644 (file)
@@ -117,6 +117,44 @@ struct dotnet_runtime_stuff {
        DISPID create_instance;
 };
 
+/* We link dynamically to mscoree.dll to avoid the hard dependency on .NET
+ * framework, which is only required if a dotnet instance is to be created.
+ */
+static HRESULT dotnet_bind_runtime(LPVOID FAR *ppv)
+{
+       HRESULT hr;
+       HMODULE mscoree;
+       typedef HRESULT (STDAPICALLTYPE *cbtr_t)(LPCWSTR pwszVersion, LPCWSTR pwszBuildFlavor, REFCLSID rclsid, REFIID riid, LPVOID FAR *ppv);
+       cbtr_t CorBindToRuntime;
+       OLECHAR *oleversion;
+       char *version;
+
+       mscoree = LoadLibraryA("mscoree.dll");
+       if (mscoree == NULL) {
+               return S_FALSE;
+       }
+
+       CorBindToRuntime = (cbtr_t) GetProcAddress(mscoree, "CorBindToRuntime");
+       if (CorBindToRuntime == NULL) {
+               FreeLibrary(mscoree);
+               return S_FALSE;
+       }
+
+       version = INI_STR("com.dotnet_version");
+       if (version == NULL || *version == '\0') {
+               oleversion = NULL;
+       } else {
+               oleversion = php_com_string_to_olestring(version, strlen(version), COMG(code_page));
+       }
+
+       hr = CorBindToRuntime(oleversion, NULL, &CLSID_CorRuntimeHost, &IID_ICorRuntimeHost, ppv);
+
+       efree(oleversion);
+       FreeLibrary(mscoree);
+
+       return hr;
+}
+
 static HRESULT dotnet_init(char **p_where)
 {
        HRESULT hr;
@@ -130,10 +168,8 @@ static HRESULT dotnet_init(char **p_where)
        }
        memset(stuff, 0, sizeof(*stuff));
 
-       where = "CoCreateInstance";
-       hr = CoCreateInstance(&CLSID_CorRuntimeHost, NULL, CLSCTX_ALL,
-                       &IID_ICorRuntimeHost, (LPVOID*)&stuff->dotnet_host);
-
+       where = "dotnet_bind_runtime";
+       hr = dotnet_bind_runtime((LPVOID*)&stuff->dotnet_host);
        if (FAILED(hr))
                goto out;
 
index 0535509412e0cecf8c7c611ce99020930e9327b6..5e2c1f69de7fb28429e729044031523c3f578923 100644 (file)
@@ -141,6 +141,7 @@ PHP_INI_BEGIN()
     STD_PHP_INI_ENTRY("com.autoregister_casesensitive",        "1", PHP_INI_ALL, OnAutoregisterCasesensitive, autoreg_case_sensitive, zend_com_dotnet_globals, com_dotnet_globals)
        STD_PHP_INI_ENTRY("com.code_page", "", PHP_INI_ALL, OnUpdateLong, code_page, zend_com_dotnet_globals, com_dotnet_globals)
        PHP_INI_ENTRY("com.typelib_file", "", PHP_INI_SYSTEM, OnTypeLibFileUpdate)
+       PHP_INI_ENTRY("com.dotnet_version", NULL, PHP_INI_SYSTEM, NULL)
 PHP_INI_END()
 /* }}} */
 
index b352f5056fbb78d595fddf017ec89582d4a92e15..54006830a2c06d97078e5c6f11046bf3a83ace3c 100644 (file)
@@ -1614,6 +1614,10 @@ zend.assertions = 1
 ; Default: system ANSI code page
 ;com.code_page=
 
+; The version of the .NET framework to use. 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".
+;com.dotnet_version=
+
 [mbstring]
 ; language for internal character representation.
 ; This affects mb_send_mail() and mbstring.detect_order.
index 61960ef807c5f7fea0bbed02288bd84f9c936f4a..47a5c5e13b20b8e1da79f6384518aa8f76fbeaf4 100644 (file)
@@ -1618,6 +1618,10 @@ zend.assertions = -1
 ; Default: system ANSI code page
 ;com.code_page=
 
+; The version of the .NET framework to use. 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".
+;com.dotnet_version=
+
 [mbstring]
 ; language for internal character representation.
 ; This affects mb_send_mail() and mbstring.detect_order.