private static int Invoke(IDispatch dispatch, int memberDispId, out object result)
        {
            Guid emptyRiid = Guid.Empty;

            ComTypes.DISPPARAMS dispParams = new ComTypes.DISPPARAMS();
            ComTypes.EXCEPINFO  excepInfo  = new ComTypes.EXCEPINFO();
            uint argErr;
            int  hresult = dispatch.TryInvoke(
                memberDispId,
                ref emptyRiid,
                0,
                ComTypes.INVOKEKIND.INVOKE_PROPERTYGET,
                ref dispParams,
                out result,
                out excepInfo,
                out argErr);

            return(hresult);
        }
        /// <summary>
        /// A basic helper for IDispatch::Invoke
        /// </summary>
        /// <param name="obj">The IDispatch object of which you want to invoke a member on</param>
        /// <param name="memberId">The dispatch ID of the member to invoke</param>
        /// <param name="invokeKind">See InvokeKind enumeration</param>
        /// <param name="args">Array of arguments to pass to the call, or null for no args</param>
        /// <remarks>TODO support DISPATCH_PROPERTYPUTREF (property-set) which requires special handling</remarks>
        /// <returns>An object representing the return value from the called routine</returns>
        public static object Invoke(IDispatch obj, int memberId, InvokeKind invokeKind, object[] args = null)
        {
            var pDispParams = PrepareDispatchArgs(args);
            var pExcepInfo  = new ComTypes.EXCEPINFO();

            var hr = obj.Invoke(memberId, ref _guid_null, 0, (uint)invokeKind,
                                ref pDispParams, out var pVarResult, ref pExcepInfo, out var pErrArg);

            UnprepareDispatchArgs(pDispParams);

            if (ComHelper.HRESULT_FAILED(hr))
            {
                if ((hr == (int)KnownComHResults.DISP_E_EXCEPTION) && (ComHelper.HRESULT_FAILED(pExcepInfo.scode)))
                {
                    throw RdMarshal.GetExceptionForHR(pExcepInfo.scode);
                }
                throw RdMarshal.GetExceptionForHR(hr);
            }

            return(pVarResult);
        }
Beispiel #3
0
 public virtual extern void InterruptScriptThread(int thread, ref System.Runtime.InteropServices.ComTypes.EXCEPINFO pexecpinfo, int dwFlags);
Beispiel #4
0
 public int OnScriptTerminate(VariantWrapper varResult, ref System.Runtime.InteropServices.ComTypes.EXCEPINFO excepInfo)
 {
     return(0);
 }
Beispiel #5
0
        static int Invoke(IDispatch dispatch, int memberDispId, out object result) {
            Guid emtpyRiid = Guid.Empty;
            ComTypes.DISPPARAMS dispParams = new ComTypes.DISPPARAMS();
            ComTypes.EXCEPINFO excepInfo = new ComTypes.EXCEPINFO();
            uint argErr;
            int hresult = dispatch.TryInvoke(
                memberDispId,
                ref emtpyRiid,
                0,
                ComTypes.INVOKEKIND.INVOKE_PROPERTYGET,
                ref dispParams,
                out result,
                out excepInfo,
                out argErr);

            return hresult;
        }
Beispiel #6
0
 /// <summary>
 /// Informs the host that the script has completed execution.
 /// </summary>
 /// <param name="result">A variable that contains the script result, or null if the script
 /// produced no result.</param>
 /// <param name="exceptionInfo">Contains exception information generated when the script
 /// terminated, or null if no exception was generated.</param>
 public virtual void OnScriptTerminate(object result, ComTypes.EXCEPINFO exceptionInfo)
 {
 }
Beispiel #7
0
 int IPseudoDispatch.Invoke(uint dispIdMember, uint cArgs, uint cNamedArgs, IntPtr rgvarg, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] uint[] rgdispidNamedArgs, IntPtr pVarResult, IntPtr pExcepInfo, out uint pArgErr)
 {
     pArgErr = 0;
     try
     {
         if (cNamedArgs > 0)
         {
             throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new COMException(System.ServiceModel.SR.GetString("NamedArgsNotSupported"), HR.DISP_E_BADPARAMCOUNT));
         }
         MethodInfo info = null;
         if (!this.dispToOperationDescription.TryGetValue(dispIdMember, out info))
         {
             throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new COMException(System.ServiceModel.SR.GetString("BadDispID", new object[] { dispIdMember }), HR.DISP_E_MEMBERNOTFOUND));
         }
         object[] ins    = null;
         object[] outs   = null;
         string   action = null;
         if (info.paramList.Count != cArgs)
         {
             throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new COMException(System.ServiceModel.SR.GetString("BadDispID", new object[] { dispIdMember }), HR.DISP_E_BADPARAMCOUNT));
         }
         ins  = new object[info.opDesc.Messages[0].Body.Parts.Count];
         outs = new object[info.opDesc.Messages[1].Body.Parts.Count];
         if (cArgs > 0)
         {
             if (info.opDesc.Messages[0].Body.Parts.Count > 0)
             {
                 for (int j = 0; j < info.opDesc.Messages[0].Body.Parts.Count; j++)
                 {
                     ins[j] = null;
                 }
             }
             if (!info.opDesc.IsOneWay && (info.opDesc.Messages[1].Body.Parts.Count > 0))
             {
                 for (int k = 0; k < info.opDesc.Messages[1].Body.Parts.Count; k++)
                 {
                     outs[k] = null;
                 }
             }
         }
         action = info.opDesc.Messages[0].Action;
         int num3 = 0;
         for (int i = 0; i < cArgs; i++)
         {
             if (info.paramList[i].inIndex != -1)
             {
                 try
                 {
                     object obj2 = null;
                     if (!info.paramList[i].type.IsArray)
                     {
                         obj2 = this.FetchVariant(rgvarg, (int)((cArgs - i) - ((ulong)1L)), info.paramList[i].type);
                     }
                     else
                     {
                         obj2 = this.FetchVariants(rgvarg, (int)((cArgs - i) - ((ulong)1L)), info.paramList[i].type);
                     }
                     ins[info.paramList[i].inIndex] = obj2;
                     num3++;
                 }
                 catch (ArgumentNullException)
                 {
                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(System.ServiceModel.SR.GetString("VariantArrayNull", new object[] { (cArgs - i) - 1L }));
                 }
             }
         }
         if (num3 != ins.Length)
         {
             throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new COMException(System.ServiceModel.SR.GetString("BadParamCount"), HR.DISP_E_BADPARAMCOUNT));
         }
         object obj3 = null;
         try
         {
             obj3 = this.SendMessage(info.opDesc, action, ins, outs);
         }
         catch (Exception baseException)
         {
             if (Fx.IsFatal(baseException))
             {
                 throw;
             }
             if (pExcepInfo != IntPtr.Zero)
             {
                 System.Runtime.InteropServices.ComTypes.EXCEPINFO structure = new System.Runtime.InteropServices.ComTypes.EXCEPINFO();
                 baseException             = baseException.GetBaseException();
                 structure.bstrDescription = baseException.Message;
                 structure.bstrSource      = baseException.Source;
                 structure.scode           = Marshal.GetHRForException(baseException);
                 Marshal.StructureToPtr(structure, pExcepInfo, false);
             }
             return(HR.DISP_E_EXCEPTION);
         }
         if (!info.opDesc.IsOneWay)
         {
             if (outs != null)
             {
                 bool[] flagArray = new bool[outs.Length];
                 for (uint m = 0; m < flagArray.Length; m++)
                 {
                     flagArray[m] = false;
                 }
                 for (int n = 0; n < cArgs; n++)
                 {
                     if (info.paramList[n].outIndex != -1)
                     {
                         try
                         {
                             if (this.IsByRef(rgvarg, (int)((cArgs - n) - ((ulong)1L))))
                             {
                                 this.PopulateByRef(rgvarg, (int)((cArgs - n) - ((ulong)1L)), outs[info.paramList[n].outIndex]);
                             }
                         }
                         catch (ArgumentNullException)
                         {
                             throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(System.ServiceModel.SR.GetString("VariantArrayNull", new object[] { (cArgs - n) - 1L }));
                         }
                         flagArray[info.paramList[n].outIndex] = true;
                     }
                 }
             }
             if ((obj3 != null) && (pVarResult != IntPtr.Zero))
             {
                 if (!obj3.GetType().IsArray)
                 {
                     Marshal.GetNativeVariantForObject(obj3, pVarResult);
                 }
                 else
                 {
                     Array array  = obj3 as Array;
                     Array array2 = Array.CreateInstance(typeof(object), array.Length);
                     array.CopyTo(array2, 0);
                     Marshal.GetNativeVariantForObject(array2, pVarResult);
                 }
             }
         }
         return(HR.S_OK);
     }
     catch (Exception exception2)
     {
         if (Fx.IsFatal(exception2))
         {
             throw;
         }
         return(Marshal.GetHRForException(exception2.GetBaseException()));
     }
 }
        /// <summary>
        /// Insert a new top level scripting object into the runtime environment of the specified
        /// HTML document.
        /// </summary>
        /// <param name="document">document to insert into</param>
        /// <param name="objectName">top-level name to refer to the object in script</param>
        /// <param name="obj">object to insert (must be marked with ComVisible attribute)</param>
        public static void InjectObjectIntoScriptingEnvironment(IHTMLDocument2 document, string objectName, object obj)
        {
            // ensure that it is marked com-visible
            ComVisibleAttribute[] comVisibleAttributes = (ComVisibleAttribute[])obj.GetType().GetCustomAttributes(typeof(ComVisibleAttribute), false);
            if (comVisibleAttributes.Length == 0 || !comVisibleAttributes[0].Value)
            {
                Debug.Fail("Objects inserted into IHTMLDocument2 scripting environment must be marked with the ComVisible(true) attribute");
                return;
            }

            // implementation constants
            const uint fdexNameEnsure = 0x00000002;
            const uint LOCALE_USER_DEFAULT = 1024;
            const Int16 DISPATCH_PROPERTYPUT = 4;
            const Int32 DISPID_PROPERTYPUT = -3;

            // buffers we will allocate (must free before exiting)
            IntPtr pPropertyPut = IntPtr.Zero;
            IntPtr pObject = IntPtr.Zero;
            try
            {
                // get pointer to IDispatchEx
                object script = document.Script;
                IDispatchEx dispatchEx = (IDispatchEx)script;

                // insert the object into the scripting environment (requires several steps)

                // insert a new dispatch-id for the object
                IntPtr dispId;
                dispatchEx.GetDispID(objectName, fdexNameEnsure, out dispId);

                // initialize structure used to pass the object in
                System.Runtime.InteropServices.ComTypes.DISPPARAMS dispParams = new System.Runtime.InteropServices.ComTypes.DISPPARAMS();
                dispParams.cArgs = 1;
                dispParams.cNamedArgs = 1;

                // indicate that this call to InvokeEx is a property put
                pPropertyPut = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(Int32)));
                Marshal.WriteInt32(pPropertyPut, DISPID_PROPERTYPUT);
                dispParams.rgdispidNamedArgs = pPropertyPut;

                // specify the object to pass to InvokeEx (we think the size of a VARIANT is ~14
                // bytes but we initialize WAY more memory just to be safe)
                pObject = Marshal.AllocCoTaskMem(256);
                Marshal.GetNativeVariantForObject(obj, pObject);
                dispParams.rgvarg = pObject;

                // initialize error structure
                System.Runtime.InteropServices.ComTypes.EXCEPINFO ei = new System.Runtime.InteropServices.ComTypes.EXCEPINFO();

                // set the object into the specified objectName (creates a new top level scripting object)
                dispatchEx.InvokeEx(
                    dispId,					// disp-id of objectName
                    LOCALE_USER_DEFAULT,	// use default locale (should this be en-US?)
                    DISPATCH_PROPERTYPUT,   // specify a property set operation
                    ref dispParams,			// parameters to pass (value to set property to)
                    IntPtr.Zero,			// pointer to result (no result for property put)
                    ref ei,					// pointer to exception structure
                    IntPtr.Zero);			// optional service provider not specified
            }
            finally
            {
                if (pPropertyPut != IntPtr.Zero)
                    Marshal.FreeCoTaskMem(pPropertyPut);
                if (pObject != IntPtr.Zero)
                    Marshal.FreeCoTaskMem(pObject);
            }
        }
Beispiel #9
0
 int IActiveScriptSite.OnScriptTerminate(object result, System.Runtime.InteropServices.ComTypes.EXCEPINFO exceptionInfo)
 {
     return(0);
 }
 int IPseudoDispatch.Invoke(uint dispIdMember, uint cArgs, uint cNamedArgs, IntPtr rgvarg, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex=2)] uint[] rgdispidNamedArgs, IntPtr pVarResult, IntPtr pExcepInfo, out uint pArgErr)
 {
     pArgErr = 0;
     try
     {
         if (cNamedArgs > 0)
         {
             throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new COMException(System.ServiceModel.SR.GetString("NamedArgsNotSupported"), HR.DISP_E_BADPARAMCOUNT));
         }
         MethodInfo info = null;
         if (!this.dispToOperationDescription.TryGetValue(dispIdMember, out info))
         {
             throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new COMException(System.ServiceModel.SR.GetString("BadDispID", new object[] { dispIdMember }), HR.DISP_E_MEMBERNOTFOUND));
         }
         object[] ins = null;
         object[] outs = null;
         string action = null;
         if (info.paramList.Count != cArgs)
         {
             throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new COMException(System.ServiceModel.SR.GetString("BadDispID", new object[] { dispIdMember }), HR.DISP_E_BADPARAMCOUNT));
         }
         ins = new object[info.opDesc.Messages[0].Body.Parts.Count];
         outs = new object[info.opDesc.Messages[1].Body.Parts.Count];
         if (cArgs > 0)
         {
             if (info.opDesc.Messages[0].Body.Parts.Count > 0)
             {
                 for (int j = 0; j < info.opDesc.Messages[0].Body.Parts.Count; j++)
                 {
                     ins[j] = null;
                 }
             }
             if (!info.opDesc.IsOneWay && (info.opDesc.Messages[1].Body.Parts.Count > 0))
             {
                 for (int k = 0; k < info.opDesc.Messages[1].Body.Parts.Count; k++)
                 {
                     outs[k] = null;
                 }
             }
         }
         action = info.opDesc.Messages[0].Action;
         int num3 = 0;
         for (int i = 0; i < cArgs; i++)
         {
             if (info.paramList[i].inIndex != -1)
             {
                 try
                 {
                     object obj2 = null;
                     if (!info.paramList[i].type.IsArray)
                     {
                         obj2 = this.FetchVariant(rgvarg, (int) ((cArgs - i) - ((ulong) 1L)), info.paramList[i].type);
                     }
                     else
                     {
                         obj2 = this.FetchVariants(rgvarg, (int) ((cArgs - i) - ((ulong) 1L)), info.paramList[i].type);
                     }
                     ins[info.paramList[i].inIndex] = obj2;
                     num3++;
                 }
                 catch (ArgumentNullException)
                 {
                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(System.ServiceModel.SR.GetString("VariantArrayNull", new object[] { (cArgs - i) - 1L }));
                 }
             }
         }
         if (num3 != ins.Length)
         {
             throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new COMException(System.ServiceModel.SR.GetString("BadParamCount"), HR.DISP_E_BADPARAMCOUNT));
         }
         object obj3 = null;
         try
         {
             obj3 = this.SendMessage(info.opDesc, action, ins, outs);
         }
         catch (Exception baseException)
         {
             if (Fx.IsFatal(baseException))
             {
                 throw;
             }
             if (pExcepInfo != IntPtr.Zero)
             {
                 System.Runtime.InteropServices.ComTypes.EXCEPINFO structure = new System.Runtime.InteropServices.ComTypes.EXCEPINFO();
                 baseException = baseException.GetBaseException();
                 structure.bstrDescription = baseException.Message;
                 structure.bstrSource = baseException.Source;
                 structure.scode = Marshal.GetHRForException(baseException);
                 Marshal.StructureToPtr(structure, pExcepInfo, false);
             }
             return HR.DISP_E_EXCEPTION;
         }
         if (!info.opDesc.IsOneWay)
         {
             if (outs != null)
             {
                 bool[] flagArray = new bool[outs.Length];
                 for (uint m = 0; m < flagArray.Length; m++)
                 {
                     flagArray[m] = false;
                 }
                 for (int n = 0; n < cArgs; n++)
                 {
                     if (info.paramList[n].outIndex != -1)
                     {
                         try
                         {
                             if (this.IsByRef(rgvarg, (int) ((cArgs - n) - ((ulong) 1L))))
                             {
                                 this.PopulateByRef(rgvarg, (int) ((cArgs - n) - ((ulong) 1L)), outs[info.paramList[n].outIndex]);
                             }
                         }
                         catch (ArgumentNullException)
                         {
                             throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(System.ServiceModel.SR.GetString("VariantArrayNull", new object[] { (cArgs - n) - 1L }));
                         }
                         flagArray[info.paramList[n].outIndex] = true;
                     }
                 }
             }
             if ((obj3 != null) && (pVarResult != IntPtr.Zero))
             {
                 if (!obj3.GetType().IsArray)
                 {
                     Marshal.GetNativeVariantForObject(obj3, pVarResult);
                 }
                 else
                 {
                     Array array = obj3 as Array;
                     Array array2 = Array.CreateInstance(typeof(object), array.Length);
                     array.CopyTo(array2, 0);
                     Marshal.GetNativeVariantForObject(array2, pVarResult);
                 }
             }
         }
         return HR.S_OK;
     }
     catch (Exception exception2)
     {
         if (Fx.IsFatal(exception2))
         {
             throw;
         }
         return Marshal.GetHRForException(exception2.GetBaseException());
     }
 }
Beispiel #11
0
 public void OnScriptTerminate(ref object result, ref EXCEPINFO info)
 {
 }
Beispiel #12
0
 void ProcessError(Exception e)
 {
     if (e.Source != null)
     {
         Log.Write(e.Message + "\n" + e.StackTrace);
         if (Initialized)
         {
             System.Runtime.InteropServices.ComTypes.EXCEPINFO ei = new System.Runtime.InteropServices.ComTypes.EXCEPINFO();
             ei.wCode = 1006; //Вид пиктограммы
             ei.bstrDescription = e.Message; //.ToString()
             ei.bstrSource = c_AddinName;
             V7Data.ErrorLog.AddError("", ref ei);
             //prClearExcInfo();
             //throw new System.Exception("An exception has occurred.");
         }
     }
 }
Beispiel #13
0
        public static T Invoke <T>(object source, InvokeFlags invokeFlags, int dispId, params object[] args)
        {
            if (source == null)
            {
                throw new ArgumentNullException("source");
            }
            if ((invokeFlags != InvokeFlags.DISPATCH_METHOD) &&
                (invokeFlags != InvokeFlags.DISPATCH_PROPERTYGET) &&
                (invokeFlags != InvokeFlags.DISPATCH_PROPERTYPUT) &&
                (invokeFlags != InvokeFlags.DISPATCH_PROPERTYPUTREF) &&
                (invokeFlags != (InvokeFlags.DISPATCH_METHOD | InvokeFlags.DISPATCH_PROPERTYGET)))
            {
                // It's acceptable to specify both DISPATCH_METHOD and DISPATCH_PROPERTYGET together
                throw new ArgumentOutOfRangeException("invokeFlags");
            }
            if (args == null)
            {
                throw new ArgumentNullException("args");
            }

            var    memoryAllocationsToFree = new List <IntPtr>();
            IntPtr rgdispidNamedArgs;
            int    cNamedArgs;

            if ((invokeFlags == InvokeFlags.DISPATCH_PROPERTYPUT) || (invokeFlags == InvokeFlags.DISPATCH_PROPERTYPUTREF))

            {
                // There must be at least one argument specified; only one if it is a non-indexed property and multiple if there are index values as well as the
                // value to set to
                if (args.Length < 1)
                {
                    throw new ArgumentException("At least one argument must be specified when DISPATCH_PROPERTYPUT(REF) is requested");
                }

                var pdPutID = Marshal.AllocCoTaskMem(sizeof(Int64));
                Marshal.WriteInt64(pdPutID, DISPID_PROPERTYPUT);
                memoryAllocationsToFree.Add(pdPutID);

                rgdispidNamedArgs = pdPutID;
                cNamedArgs        = 1;
            }
            else
            {
                rgdispidNamedArgs = IntPtr.Zero;
                cNamedArgs        = 0;
            }

            var    variantsToClear = new List <IntPtr>();
            IntPtr rgvarg;

            if (args.Length == 0)
            {
                rgvarg = IntPtr.Zero;
            }
            else
            {
                // We need to allocate enough memory to store a variant for each argument (and then populate this memory)
                rgvarg = Marshal.AllocCoTaskMem(SizeOfNativeVariant * args.Length);
                memoryAllocationsToFree.Add(rgvarg);
                for (var index = 0; index < args.Length; index++)
                {
                    // Note: The "IDispatch::Invoke method (Automation)" page (http://msdn.microsoft.com/en-us/library/windows/desktop/ms221479(v=vs.85).aspx)
                    // states that "Arguments are stored in pDispParams->rgvarg in reverse order" so we'll reverse them here
                    var arg = args[(args.Length - 1) - index];

                    // According to http://stackoverflow.com/a/1866268 it seems like using ToInt64 here will be valid for both 32 and 64 bit machines. While
                    // this may apparently not be the most performant approach, it should do the job.
                    // Don't think we have to worry about pinning any references when we do this manipulation here since we are allocating the array in
                    // unmanaged memory and so the garbage collector won't be moving anything around (and GetNativeVariantForObject copies the reference
                    // and automatic pinning will prevent the GC from interfering while this is happening).
                    var pVariant = new IntPtr(
                        rgvarg.ToInt64() + (SizeOfNativeVariant * index)
                        );
                    Marshal.GetNativeVariantForObject(arg, pVariant);
                    variantsToClear.Add(pVariant);
                }
            }

            var dispParams = new ComTypes.DISPPARAMS()
            {
                cArgs             = args.Length,
                rgvarg            = rgvarg,
                cNamedArgs        = cNamedArgs,
                rgdispidNamedArgs = rgdispidNamedArgs
            };

            try
            {
                var    IID_NULL = new Guid("00000000-0000-0000-0000-000000000000");
                UInt32 pArgErr  = 0;
                object varResult;
                var    excepInfo = new ComTypes.EXCEPINFO();
                var    hrRet     = ((IDispatch)source).Invoke
                                   (
                    dispId,
                    ref IID_NULL,
                    LOCALE_SYSTEM_DEFAULT,
                    (ushort)invokeFlags,
                    ref dispParams,
                    out varResult,
                    ref excepInfo,
                    out pArgErr
                                   );
                if (hrRet != 0)
                {
                    var errorType = GetErrorMessageForHResult(hrRet);
                    if (errorType == CommonErrors.DISP_E_MEMBERNOTFOUND)
                    {
                        throw new IDispatchAccessException("Member not found", source, memberNameIfSpecified: null, dispIdIfKnown: dispId, errorType: errorType);
                    }
                    var message = "Failing attempting to invoke method with DispId " + dispId + ": ";
                    if ((excepInfo.bstrDescription ?? "").Trim() == "")
                    {
                        message += "Unspecified error";
                    }
                    else
                    {
                        message += excepInfo.bstrDescription;
                    }
                    if (errorType != CommonErrors.Unknown)
                    {
                        message += " [" + errorType.ToString() + "]";
                    }
                    if (args.Length > 0)
                    {
                        try { Marshal.GetObjectsForNativeVariants(rgvarg, args.Length); }
                        catch (Exception)
                        {
                            // In Visual Studio 2012, if the "Prefer 32-bit" build option is not enabled then arguments do not get written into memory
                            // correctly which will result in the request failing. If an exception has been raised then we can confirm if this is the
                            // problem by trying to pull the arguments back out of the "rgvarg", if this operation fails then the absence of this
                            // build option is most likely the cause.
                            message += " - this may be due to the \"Prefer 32-bit\" option not being enabled in Visual Studio";
                        }
                    }
                    throw new IDispatchAccessException(message, source, memberNameIfSpecified: null, dispIdIfKnown: dispId, errorType: errorType);
                }
                return((T)varResult);
            }
            finally
            {
                foreach (var variantToClear in variantsToClear)
                {
                    VariantClear(variantToClear);
                }

                foreach (var memoryAllocationToFree in memoryAllocationsToFree)
                {
                    Marshal.FreeCoTaskMem(memoryAllocationToFree);
                }
            }
        }
        private static T Invoke <T>(object source, InvokeFlags invokeFlags, int dispId, params object[] args)
        {
            if (source == null)
            {
                throw new ArgumentNullException("source");
            }
            if (!Enum.IsDefined(typeof(InvokeFlags), invokeFlags))
            {
                throw new ArgumentOutOfRangeException("invokeFlags");
            }
            if (args == null)
            {
                throw new ArgumentNullException("args");
            }

            var    memoryAllocationsToFree = new List <IntPtr>();
            IntPtr rgdispidNamedArgs;
            int    cNamedArgs;

            if ((invokeFlags == InvokeFlags.DISPATCH_PROPERTYPUT) || (invokeFlags == InvokeFlags.DISPATCH_PROPERTYPUTREF))
            {
                // There must be at least one argument specified; only one if it is a non-indexed property and multiple if there are index values as well as the
                // value to set to
                if (args.Length < 1)
                {
                    throw new ArgumentException("At least one argument must be specified when DISPATCH_PROPERTYPUT is requested");
                }

                var pdPutID = Marshal.AllocCoTaskMem(sizeof(Int64));
                Marshal.WriteInt64(pdPutID, DISPID_PROPERTYPUT);
                memoryAllocationsToFree.Add(pdPutID);

                rgdispidNamedArgs = pdPutID;
                cNamedArgs        = 1;
            }
            else
            {
                rgdispidNamedArgs = IntPtr.Zero;
                cNamedArgs        = 0;
            }

            var    variantsToClear = new List <IntPtr>();
            IntPtr rgvarg;

            if (args.Length == 0)
            {
                rgvarg = IntPtr.Zero;
            }
            else
            {
                // We need to allocate enough memory to store a variant for each argument (and then populate this memory)
                rgvarg = Marshal.AllocCoTaskMem(SizeOfNativeVariant * args.Length);
                memoryAllocationsToFree.Add(rgvarg);
                for (var index = 0; index < args.Length; index++)
                {
                    // Note: The "IDispatch::Invoke method (Automation)" page (http://msdn.microsoft.com/en-us/library/windows/desktop/ms221479(v=vs.85).aspx)
                    // states that "Arguments are stored in pDispParams->rgvarg in reverse order" so we'll reverse them here
                    var arg = args[(args.Length - 1) - index];

                    // According to http://stackoverflow.com/a/1866268 it seems like using ToInt64 here will be valid for both 32 and 64 bit machines. While
                    // this may apparently not be the most performant approach, it should do the job.
                    // Don't think we have to worry about pinning any references when we do this manipulation here since we are allocating the array in
                    // unmanaged memory and so the garbage collector won't be moving anything around (and GetNativeVariantForObject copies the reference
                    // and automatic pinning will prevent the GC from interfering while this is happening).
                    var pVariant = new IntPtr(
                        rgvarg.ToInt64() + (SizeOfNativeVariant * index)
                        );
                    Marshal.GetNativeVariantForObject(arg, pVariant);
                    variantsToClear.Add(pVariant);
                }
            }

            var dispParams = new ComTypes.DISPPARAMS()
            {
                cArgs             = args.Length,
                rgvarg            = rgvarg,
                cNamedArgs        = cNamedArgs,
                rgdispidNamedArgs = rgdispidNamedArgs
            };

            try
            {
                var    IID_NULL = new Guid("00000000-0000-0000-0000-000000000000");
                UInt32 pArgErr  = 0;
                object varResult;
                var    excepInfo = new ComTypes.EXCEPINFO();
                var    hrRet     = ((IDispatch)source).Invoke
                                   (
                    dispId,
                    ref IID_NULL,
                    LOCALE_SYSTEM_DEFAULT,
                    (ushort)invokeFlags,
                    ref dispParams,
                    out varResult,
                    ref excepInfo,
                    out pArgErr
                                   );
                if (hrRet != 0)
                {
                    if (excepInfo.bstrDescription == null)
                    {
                        Console.WriteLine($"Exception thrown while accessing {TypeDescriptor.GetClassName(source)} has null bstrDescription");
                    }
                    else
                    {
                        Console.WriteLine($"Exception thrown while accessing {TypeDescriptor.GetClassName(source)} has bstrDescription: \"{excepInfo.bstrDescription}\"");
                    }

                    // Try to translate the exception back into a COMSurvivableException - if this is not possible then fall through to the code below
                    COMSurvivableException.RethrowAsOriginalIfPossible(
                        new COMException(excepInfo.bstrDescription, excepInfo.scode)
                        );
                    var message   = "Failing attempting to invoke method with DispId " + dispId + ": ";
                    var errorType = GetErrorMessageForHResult(hrRet);
                    if (errorType == CommonErrors.DISP_E_MEMBERNOTFOUND)
                    {
                        message += "Member not found";
                    }
                    else if (!string.IsNullOrWhiteSpace(excepInfo.bstrDescription))
                    {
                        message += excepInfo.bstrDescription;
                    }
                    else
                    {
                        message += "Unspecified error";
                        if (errorType != CommonErrors.Unknown)
                        {
                            message += " [" + errorType.ToString() + "]";
                        }
                    }
                    throw new ArgumentException(message);
                }
                return((T)varResult);
            }
            finally
            {
                foreach (var variantToClear in variantsToClear)
                {
                    VariantClear(variantToClear);
                }

                foreach (var memoryAllocationToFree in memoryAllocationsToFree)
                {
                    Marshal.FreeCoTaskMem(memoryAllocationToFree);
                }
            }
        }
        public int AddError(string Desc, System.Runtime.InteropServices.ComTypes.EXCEPINFO ex)
        {
            Debug.WriteLine(Desc);

            return(0);
        }
 int IProxyManager.Invoke(uint dispIdMember, IntPtr outerProxy, IntPtr pVarResult, IntPtr pExcepInfo)
 {
     try
     {
         Guid gUID;
         ComProxy comProxy = null;
         if (dispIdMember == 1)
         {
             gUID = typeof(IChannelOptions).GUID;
         }
         else if (dispIdMember == 2)
         {
             gUID = typeof(IChannelCredentials).GUID;
         }
         else
         {
             return HR.DISP_E_MEMBERNOTFOUND;
         }
         this.FindOrCreateProxyInternal(outerProxy, ref gUID, out comProxy);
         TagVariant structure = new TagVariant {
             vt = 9
         };
         IntPtr zero = IntPtr.Zero;
         comProxy.QueryInterface(ref gUID, out zero);
         structure.ptr = zero;
         Marshal.StructureToPtr(structure, pVarResult, true);
         return HR.S_OK;
     }
     catch (Exception baseException)
     {
         if (Fx.IsFatal(baseException))
         {
             throw;
         }
         if (pExcepInfo != IntPtr.Zero)
         {
             System.Runtime.InteropServices.ComTypes.EXCEPINFO excepinfo = new System.Runtime.InteropServices.ComTypes.EXCEPINFO();
             baseException = baseException.GetBaseException();
             excepinfo.bstrDescription = baseException.Message;
             excepinfo.bstrSource = baseException.Source;
             excepinfo.scode = Marshal.GetHRForException(baseException);
             Marshal.StructureToPtr(excepinfo, pExcepInfo, false);
         }
         return HR.DISP_E_EXCEPTION;
     }
 }