/* * DesktopComUtils.cpp * * Copyright (C) 2009-18 by RStudio, PBC * * Unless you have received this program directly from RStudio pursuant * to the terms of a commercial license agreement with RStudio, then * this program is licensed to you under the terms of version 3 of the * GNU Affero General Public License. This program is distributed WITHOUT * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT, * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details. * */ #include #include #include #include #include #include "DesktopComUtils.hpp" namespace rstudio { namespace desktop { // Invoke a method or property by name on the given IDispatch interface. // Adapted from the standard automation AutoWrap helper function // (see http://support.microsoft.com/kb/238393) HRESULT invokeDispatch (int dispatchType, VARIANT *pvResult, IDispatch *pDisp, const std::wstring& strName, int cArgs...) { va_list marker; va_start(marker, cArgs); DISPPARAMS dp = { nullptr, nullptr, 0, 0 }; DISPID dispidNamed = DISPID_PROPERTYPUT; DISPID dispID; HRESULT hr; LPOLESTR wstrName = const_cast(strName.c_str()); hr = pDisp->GetIDsOfNames(IID_NULL, &wstrName, 1, LOCALE_USER_DEFAULT, &dispID); if (FAILED(hr)) return hr; // Create the argument list boost::scoped_array spArgs(new VARIANT[cArgs + 1]); for (int i = 0; i < cArgs; i++) { VARIANT varArg = va_arg(marker, VARIANT); spArgs[i] = varArg; } dp.cArgs = cArgs; dp.rgvarg = spArgs.get(); // Handle special case: for property put, we need to use named args if (dispatchType & DISPATCH_PROPERTYPUT) { dp.cNamedArgs = 1; dp.rgdispidNamedArgs = &dispidNamed; } EXCEPINFO excep; hr = pDisp->Invoke(dispID, IID_NULL, LOCALE_SYSTEM_DEFAULT, dispatchType, &dp, pvResult, &excep, nullptr); va_end(marker); return hr; } // Given an IDispatch pointer and a name, return an IDispatch pointer to the // object property with the given name HRESULT getIDispatchProp(IDispatch* idispIn, const std::wstring& strName, IDispatch** pidispOut) { VARIANT result; VariantInit(&result); HRESULT hr = invokeDispatch(DISPATCH_PROPERTYGET, &result, idispIn, strName, 0); if (FAILED(hr)) return hr; *pidispOut = result.pdispVal; return hr; } HRESULT getIntProp(IDispatch* idisp, const std::wstring& strName, int* pOut) { VARIANT result; VariantInit(&result); HRESULT hr = invokeDispatch(DISPATCH_PROPERTYGET, &result, idisp, strName, 0); if (FAILED(hr)) return hr; *pOut = result.intVal; return hr; } } // namespace desktop } // namespace rstudio