internal static IInvokeAsyncResult BeginInvokeMethod(VirtualMachine vm, ThreadMirror thread, MethodMirror method, Value this_obj, IList <Value> arguments, InvokeOptions options, AsyncCallback callback, object state) { if (thread == null) { throw new ArgumentNullException("thread"); } if (method == null) { throw new ArgumentNullException("method"); } if (arguments == null) { arguments = new Value [0]; } InvokeFlags f = InvokeFlags.NONE; if ((options & InvokeOptions.DisableBreakpoints) != 0) { f |= InvokeFlags.DISABLE_BREAKPOINTS; } if ((options & InvokeOptions.SingleThreaded) != 0) { f |= InvokeFlags.SINGLE_THREADED; } InvokeAsyncResult r = new InvokeAsyncResult { AsyncState = state, AsyncWaitHandle = new ManualResetEvent(false), VM = vm, Thread = thread, Callback = callback }; r.ID = vm.conn.VM_BeginInvokeMethod(thread.Id, method.Id, this_obj != null ? vm.EncodeValue(this_obj) : vm.EncodeValue(vm.CreateValue(null)), vm.EncodeValues(arguments), f, InvokeCB, r); return(r); }
private static object Invoke(IExpando instance, string functionName, InvokeFlags flags, object[] args) { try { args = args.Select(arg => DynamicNode.Unwrap(arg)).ToArray(); switch (flags) { case InvokeFlags.DISPATCH_METHOD: var method = instance.GetMethod(functionName, DefaultFlags); return(method.Invoke(instance, args)); case InvokeFlags.DISPATCH_PROPERTYGET: var getProp = instance.GetProperty(functionName, DefaultFlags); return(getProp.GetValue(instance, null)); case InvokeFlags.DISPATCH_PROPERTYPUT: case InvokeFlags.DISPATCH_PROPERTYPUTREF: var setProp = instance.GetProperty(functionName, DefaultFlags); if (setProp == null) { setProp = instance.AddProperty(functionName); } setProp.SetValue(instance, args[0], null); return(null); default: throw new NotSupportedException(); } } catch (COMException comex) { switch ((uint)comex.ErrorCode) { // Unexpected script error. This will be handled by the IProcess.UnhandledException event case 0x80020101: return(null); default: throw; } } }
public static T Invoke <T>(object source, InvokeFlags invokeFlags, string name, 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) { // 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 for DISPATCH_PROPERTYPUT"); } 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 System.Runtime.InteropServices.ComTypes.DISPPARAMS() { cArgs = args.Length, rgvarg = rgvarg, cNamedArgs = cNamedArgs, rgdispidNamedArgs = rgdispidNamedArgs }; try { var dispId = GetDispId(source, name); var IID_NULL = new Guid("00000000-0000-0000-0000-000000000000"); UInt32 pArgErr = 0; object varResult; var excepInfo = new System.Runtime.InteropServices.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 message = "Failing attempting to invoke method with DispId " + dispId + ": "; if ((excepInfo.bstrDescription ?? "").Trim() == "") { message += "Unspecified error"; } else { message += excepInfo.bstrDescription; } var errorType = GetErrorMessageForHResult(hrRet); 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); } } }
internal ValueImpl VM_InvokeMethod(long thread, long method, ValueImpl this_arg, ValueImpl[] arguments, InvokeFlags flags, out ValueImpl exc) { exc = null; PacketReader r = SendReceive (CommandSet.VM, (int)CmdVM.INVOKE_METHOD, new PacketWriter ().WriteId (thread).WriteInt ((int)flags).WriteId (method).WriteValue (this_arg).WriteInt (arguments.Length).WriteValues (arguments)); if (r.ReadByte () == 0) { exc = r.ReadValue (); return null; } else { return r.ReadValue (); } }
internal int VM_BeginInvokeMethods(long thread, long[] methods, ValueImpl this_arg, List<ValueImpl[]> arguments, InvokeFlags flags, InvokeMethodCallback callback, object state) { // FIXME: Merge this with INVOKE_METHOD var w = new PacketWriter (); w.WriteId (thread); w.WriteInt ((int)flags); w.WriteInt (methods.Length); for (int i = 0; i < methods.Length; ++i) { w.WriteId (methods [i]); w.WriteValue (this_arg); w.WriteInt (arguments [i].Length); w.WriteValues (arguments [i]); } return Send (CommandSet.VM, (int)CmdVM.INVOKE_METHODS, w, delegate (PacketReader r) { ValueImpl v, exc, out_this = null; ValueImpl[] out_args = null; if (r.ErrorCode != 0) { callback (null, null, null, null, (ErrorCode)r.ErrorCode, state); } else { read_invoke_res (r, out v, out exc, out out_this, out out_args); callback (v, exc, out_this, out_args, 0, state); } }, methods.Length); }
internal int VM_BeginInvokeMethod(long thread, long method, ValueImpl this_arg, ValueImpl[] arguments, InvokeFlags flags, InvokeMethodCallback callback, object state) { return Send (CommandSet.VM, (int)CmdVM.INVOKE_METHOD, new PacketWriter ().WriteId (thread).WriteInt ((int)flags).WriteId (method).WriteValue (this_arg).WriteInt (arguments.Length).WriteValues (arguments), delegate (PacketReader r) { ValueImpl v, exc, out_this = null; ValueImpl[] out_args = null; if (r.ErrorCode != 0) { callback (null, null, null, null, (ErrorCode)r.ErrorCode, state); } else { read_invoke_res (r, out v, out exc, out out_this, out out_args); callback (v, exc, out_this, out_args, 0, state); } }, 1); }
internal int VM_BeginInvokeMethod (long thread, long method, ValueImpl this_arg, ValueImpl[] arguments, InvokeFlags flags, InvokeMethodCallback callback, object state) { return Send (CommandSet.VM, (int)CmdVM.INVOKE_METHOD, new PacketWriter ().WriteId (thread).WriteInt ((int)flags).WriteId (method).WriteValue (this_arg).WriteInt (arguments.Length).WriteValues (arguments), delegate (PacketReader r) { ValueImpl v, exc; if (r.ErrorCode != 0) { callback (null, null, (ErrorCode)r.ErrorCode, state); } else { if (r.ReadByte () == 0) { exc = r.ReadValue (); v = null; } else { v = r.ReadValue (); exc = null; } callback (v, exc, 0, state); } }, 1); }
// // Implementation of InvokeMultiple // internal static IInvokeAsyncResult BeginInvokeMultiple(VirtualMachine vm, ThreadMirror thread, MethodMirror[] methods, Value this_obj, IList <IList <Value> > arguments, InvokeOptions options, AsyncCallback callback, object state) { if (thread == null) { throw new ArgumentNullException("thread"); } if (methods == null) { throw new ArgumentNullException("methods"); } foreach (var m in methods) { if (m == null) { throw new ArgumentNullException("method"); } } if (arguments == null) { arguments = new List <IList <Value> > (); for (int i = 0; i < methods.Length; ++i) { arguments.Add(new Value [0]); } } else { // FIXME: Not needed for property evaluation throw new NotImplementedException(); } if (callback == null) { throw new ArgumentException("A callback argument is required for this method.", "callback"); } InvokeFlags f = InvokeFlags.NONE; if ((options & InvokeOptions.DisableBreakpoints) != 0) { f |= InvokeFlags.DISABLE_BREAKPOINTS; } if ((options & InvokeOptions.SingleThreaded) != 0) { f |= InvokeFlags.SINGLE_THREADED; } InvokeAsyncResult r = new InvokeAsyncResult { AsyncState = state, AsyncWaitHandle = new ManualResetEvent(false), VM = vm, Thread = thread, Callback = callback, NumPending = methods.Length, IsMultiple = true }; var mids = new long [methods.Length]; for (int i = 0; i < methods.Length; ++i) { mids [i] = methods [i].Id; } var args = new List <ValueImpl[]> (); for (int i = 0; i < methods.Length; ++i) { args.Add(vm.EncodeValues(arguments [i])); } r.ID = vm.conn.VM_BeginInvokeMethods(thread.Id, mids, this_obj != null ? vm.EncodeValue(this_obj) : vm.EncodeValue(vm.CreateValue(null)), args, f, InvokeMultipleCB, r); return(r); }
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); } } }