/// <summary> /// Convert input args into a contiguous array of real COM VARIANTs for the DISPPARAMS struct used by IDispatch::Invoke /// see https://msdn.microsoft.com/en-us/library/windows/desktop/ms221416(v=vs.85).aspx /// </summary> /// <param name="args">An array of arguments to wrap</param> /// <returns><see cref="ComTypes.DISPPARAMS"/> structure ready to pass to IDispatch::Invoke</returns> private static ComTypes.DISPPARAMS PrepareDispatchArgs(object[] args) { var pDispParams = new ComTypes.DISPPARAMS(); if ((args != null) && (args.Length != 0)) { var variantStructSize = RdMarshal.SizeOf(typeof(VARIANT)); pDispParams.cArgs = args.Length; var argsVariantLength = variantStructSize * pDispParams.cArgs; var variantArgsArray = RdMarshal.AllocHGlobal(argsVariantLength); // In IDispatch::Invoke, arguments are passed in reverse order var variantArgsArrayOffset = variantArgsArray + argsVariantLength; foreach (var arg in args) { variantArgsArrayOffset -= variantStructSize; RdMarshal.GetNativeVariantForObject(arg, variantArgsArrayOffset); } pDispParams.rgvarg = variantArgsArray; } return(pDispParams); }