From 252b52ac5afb68295b21a6b0048f846b1559d544 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Fri, 14 Feb 2025 17:44:43 +0100 Subject: [PATCH] Improve COM ctor exception code for failing ProgIDs (GH-17673) The `$module_name` of `com::__construct()` can be a ProgID, ClassID or moniker. We first try `CLSIDFromString()`, and if that fails, we go ahead and try to treat the `$module_name` as a moniker. If that also fails, we throw an exception with the result of `MkParseDisplayName()` what would just be `MK_E_SYNTAX` if given a ProgID. This result is highly confusing for the common case where a ProgID is given, which is not registered (e.g. due to a typo). In this case, we use the original `HRESULT` (`CO_E_CLASSSTRING`) instead. --- ext/com_dotnet/com_com.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/ext/com_dotnet/com_com.c b/ext/com_dotnet/com_com.c index 05c2f98e903..cf44858c93b 100644 --- a/ext/com_dotnet/com_com.c +++ b/ext/com_dotnet/com_com.c @@ -38,7 +38,7 @@ PHP_METHOD(com, __construct) OLECHAR *moniker; CLSID clsid; CLSCTX ctx = CLSCTX_SERVER; - HRESULT res = E_FAIL; + HRESULT res = E_FAIL, res2; ITypeLib *TL = NULL; COSERVERINFO info; COAUTHIDENTITY authid = {0}; @@ -142,7 +142,7 @@ PHP_METHOD(com, __construct) } } - if (FAILED(CLSIDFromString(moniker, &clsid))) { + if (FAILED(res2 = CLSIDFromString(moniker, &clsid))) { /* try to use it as a moniker */ IBindCtx *pBindCtx = NULL; IMoniker *pMoniker = NULL; @@ -182,6 +182,9 @@ PHP_METHOD(com, __construct) if (pBindCtx) { IBindCtx_Release(pBindCtx); } + if (FAILED(res) && res2 == CO_E_CLASSSTRING && !wcspbrk(moniker, L"\\:")) { + res = res2; + } } else if (server_name) { MULTI_QI qi;