Example #1
0
        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;
            }
        }
    }
Example #3
0
        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);
                }
            }
        }
Example #4
0
 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 ();
     }
 }
Example #5
0
        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);
        }
Example #6
0
        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);
        }
Example #7
0
		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);
		}
Example #8
0
        //
        // 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);
        }
Example #9
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);
                }
            }
        }