From 4d54037ad30005db642f4295ebf6b71f2c012c21 Mon Sep 17 00:00:00 2001 From: Dennis Korpel Date: Tue, 9 Jul 2024 14:20:25 +0200 Subject: [PATCH] com.d: deduplicate error handling of `Invoke` --- com.d | 147 +++++++++++++++++----------------------------------------- 1 file changed, 42 insertions(+), 105 deletions(-) diff --git a/com.d b/com.d index e2cf8d0..a1d10da 100644 --- a/com.d +++ b/com.d @@ -288,32 +288,8 @@ struct ComProperty { &argError // arg error );//, "Invoke"); - import std.conv; - if(FAILED(hr)) { - if(hr == DISP_E_EXCEPTION) { - auto code = einfo.scode ? einfo.scode : einfo.wCode; - string source; - string description; - if(einfo.bstrSource) { - // this is really a wchar[] but it needs to be freed so.... - source = einfo.bstrSource[0 .. SysStringLen(einfo.bstrSource)].to!string; - SysFreeString(einfo.bstrSource); - } - if(einfo.bstrDescription) { - description = einfo.bstrDescription[0 .. SysStringLen(einfo.bstrDescription)].to!string; - SysFreeString(einfo.bstrDescription); - } - if(einfo.bstrHelpFile) { - // FIXME: we could prolly use this too - SysFreeString(einfo.bstrHelpFile); - // and dwHelpContext - } - - throw new ComException(code, description ~ " (from com source " ~ source ~ ")"); - - } else { - throw new ComException(hr, "Property get failed " ~ to!string(argError)); - } + if (Exception e = exceptionFromComResult(hr, einfo, argError, "Property get")) { + throw e; } return ComResult(result); @@ -350,32 +326,8 @@ struct ComProperty { VariantClear(&vargs[0]); - import std.conv; - if(FAILED(hr)) { - if(hr == DISP_E_EXCEPTION) { - auto code = einfo.scode ? einfo.scode : einfo.wCode; - string source; - string description; - if(einfo.bstrSource) { - // this is really a wchar[] but it needs to be freed so.... - source = einfo.bstrSource[0 .. SysStringLen(einfo.bstrSource)].to!string; - SysFreeString(einfo.bstrSource); - } - if(einfo.bstrDescription) { - description = einfo.bstrDescription[0 .. SysStringLen(einfo.bstrDescription)].to!string; - SysFreeString(einfo.bstrDescription); - } - if(einfo.bstrHelpFile) { - // FIXME: we could prolly use this too - SysFreeString(einfo.bstrHelpFile); - // and dwHelpContext - } - - throw new ComException(code, description ~ " (from com source " ~ source ~ ")"); - - } else { - throw new ComException(hr, "Property put failed " ~ to!string(argError)); - } + if (Exception e = exceptionFromComResult(hr, einfo, argError, "Property put")) { + throw e; } return rhs; @@ -463,39 +415,48 @@ struct ComProperty { } } - import std.conv; - if(FAILED(hr)) { - if(hr == DISP_E_EXCEPTION) { - auto code = einfo.scode ? einfo.scode : einfo.wCode; - string source; - string description; - if(einfo.bstrSource) { - // this is really a wchar[] but it needs to be freed so.... - source = einfo.bstrSource[0 .. SysStringLen(einfo.bstrSource)].to!string; - SysFreeString(einfo.bstrSource); - } - if(einfo.bstrDescription) { - description = einfo.bstrDescription[0 .. SysStringLen(einfo.bstrDescription)].to!string; - SysFreeString(einfo.bstrDescription); - } - if(einfo.bstrHelpFile) { - // FIXME: we could prolly use this too - SysFreeString(einfo.bstrHelpFile); - // and dwHelpContext - } - - throw new ComException(code, description ~ " (from com source " ~ source ~ ")"); - - } else { - import std.conv; - throw new ComException(hr, "Call failed " ~ to!string(cast(void*) innerComObject_) ~ " " ~ to!string(dispid) ~ " " ~ to!string(argError)); - } + if (Exception e = exceptionFromComResult(hr, einfo, argError, "Call")) { + throw e; } return ComResult(result); } } +/// Returns: `null` on success, a D Exception created from `einfo` and `argError` +/// in case the COM return `hr` signals failure +private Exception exceptionFromComResult(HRESULT hr, ref EXCEPINFO einfo, uint argError, string action) +{ + import std.conv; + if(FAILED(hr)) { + if(hr == DISP_E_EXCEPTION) { + auto code = einfo.scode ? einfo.scode : einfo.wCode; + string source; + string description; + if(einfo.bstrSource) { + // this is really a wchar[] but it needs to be freed so.... + source = einfo.bstrSource[0 .. SysStringLen(einfo.bstrSource)].to!string; + SysFreeString(einfo.bstrSource); + } + if(einfo.bstrDescription) { + description = einfo.bstrDescription[0 .. SysStringLen(einfo.bstrDescription)].to!string; + SysFreeString(einfo.bstrDescription); + } + if(einfo.bstrHelpFile) { + // FIXME: we could prolly use this too + SysFreeString(einfo.bstrHelpFile); + // and dwHelpContext + } + + throw new ComException(code, description ~ " (from com source " ~ source ~ ")"); + + } else { + throw new ComException(hr, action ~ " failed " ~ to!string(argError)); + } + } + return null; +} + /// struct ComClient(DVersion, ComVersion = IDispatch) { ComVersion innerComObject_; @@ -584,32 +545,8 @@ struct ComClient(DVersion, ComVersion = IDispatch) { } } - import std.conv; - if(FAILED(hr)) { - if(hr == DISP_E_EXCEPTION) { - auto code = einfo.scode ? einfo.scode : einfo.wCode; - string source; - string description; - if(einfo.bstrSource) { - // this is really a wchar[] but it needs to be freed so.... - source = einfo.bstrSource[0 .. SysStringLen(einfo.bstrSource)].to!string; - SysFreeString(einfo.bstrSource); - } - if(einfo.bstrDescription) { - description = einfo.bstrDescription[0 .. SysStringLen(einfo.bstrDescription)].to!string; - SysFreeString(einfo.bstrDescription); - } - if(einfo.bstrHelpFile) { - // FIXME: we could prolly use this too - SysFreeString(einfo.bstrHelpFile); - // and dwHelpContext - } - - throw new ComException(code, description ~ " (from com source " ~ source ~ ")"); - - } else { - throw new ComException(hr, "Call failed " ~ memberName ~ " " ~ to!string(argError)); - } + if (Exception e = exceptionFromComResult(hr, einfo, argError, "Call")) { + throw e; } return getFromVariant!(typeof(return))(result);