Ejemplo n.º 1
0
        /// <summary>
        /// Executes an Active Scripting function defined in the HTML document currently loaded in the WebBrowser control.
        /// </summary>
        /// <param name="scriptName">The name of the script method to invoke.</param>
        /// <param name="args"></param>
        /// <returns>The object returned by the Active Scripting call.</returns>
        public object InvokeScript(string scriptName, params object[] args)
        {
            VerifyAccess();

            if (string.IsNullOrEmpty(scriptName))
            {
                throw new ArgumentNullException("scriptName");
            }

            UnsafeNativeMethods.IDispatchEx    scriptObjectEx = null;
            UnsafeNativeMethods.IHTMLDocument2 htmlDocument   = NativeHTMLDocument;
            if (htmlDocument != null)
            {
                scriptObjectEx = htmlDocument.GetScript() as UnsafeNativeMethods.IDispatchEx;
            }

            // Protect against the cross domain scripting attacks.
            // We rely on the site locking feature in gerneral. But in IE 6 server side redirect is not blocked.
            // (In IE 7 it is blocked by turning on the DOCHOSTUIFLAG.ENABLE_REDIRECT_NOTIFICATION flag so that
            // the additional BeforeNavigate2 event is fired for server side redirect.)

            object retVal = null;

            if (scriptObjectEx != null)
            {
                NativeMethods.DISPPARAMS dp = new NativeMethods.DISPPARAMS();
                dp.rgvarg = IntPtr.Zero;
                try
                {
                    // If we use reflection to call script code, we need to Assert for the UnmanagedCode permission.
                    // But it will be a security issue when the WPF app makes a framework object available to the
                    // hosted script via ObjectForScripting or as paramter of InvokeScript, and calls the framework
                    // API that demands the UnmanagedCode permission. We do not want the demand to succeed. However,
                    // The stack walk will igore the native frames and keeps going until it reaches the Assert.
                    // That is why we switch to invoking the script via IDispatch with SUCS on the methods.
                    Guid     guid    = Guid.Empty;
                    string[] names   = new string[] { scriptName };
                    int[]    dispids = new int[] { NativeMethods.DISPID_UNKNOWN };

                    HRESULT hr = scriptObjectEx.GetIDsOfNames(ref guid, names, 1, Thread.CurrentThread.CurrentCulture.LCID, dispids);
                    hr.ThrowIfFailed();

                    if (args != null)
                    {
                        // Reverse the arg order so that parms read naturally after IDispatch. (WinForms bug 187662)
                        Array.Reverse(args);
                    }
                    dp.rgvarg            = (args == null) ? IntPtr.Zero : UnsafeNativeMethods.ArrayToVARIANTHelper.ArrayToVARIANTVector(args);
                    dp.cArgs             = (uint)((args == null) ? 0 : args.Length);
                    dp.rgdispidNamedArgs = IntPtr.Zero;
                    dp.cNamedArgs        = 0;

                    // It's important to use IDispatchEx::InvokeEx here rather than the non-Ex versions for security reasons.
                    // This version allows us to pass the IServiceProvider for security context.
                    //
                    // Calling window.open from within WPF WebBrowser control results in Access Denied script error
                    // Providing a service provider to InvokeEx only makes sense when nesting occurs (for e.g., when WPF calls
                    // a script which calls back into WPF which in turn calls the script again) and there is a need to maintain
                    // the service provider chain. When the execution is from a root occurance, then there is no valid service
                    // provider that will have all of the information from the stack.
                    //
                    // Until recently, IE was ignoring bad service providers -so our passing (IServiceProvider)htmlDocument to InvokeEx
                    // worked. IE has recently taken a security fix to ensure that it doesn't fall back to the last IOleCommandTarget
                    // in the chain it found - so now we simply pass null to indicate that this is the root call site.

                    hr = scriptObjectEx.InvokeEx(
                        dispids[0],
                        Thread.CurrentThread.CurrentCulture.LCID,
                        NativeMethods.DISPATCH_METHOD,
                        dp,
                        out retVal,
                        new NativeMethods.EXCEPINFO(),
                        null);
                    hr.ThrowIfFailed();
                }
                finally
                {
                    if (dp.rgvarg != IntPtr.Zero)
                    {
                        UnsafeNativeMethods.ArrayToVARIANTHelper.FreeVARIANTVector(dp.rgvarg, args.Length);
                    }
                }
            }
            else
            {
                throw new InvalidOperationException(SR.Get(SRID.CannotInvokeScript));
            }
            return(retVal);
        }
Ejemplo n.º 2
0
        public object InvokeScript(string scriptName, params object[] args)
        {
            base.VerifyAccess();
            if (string.IsNullOrEmpty(scriptName))
            {
                throw new ArgumentNullException("scriptName");
            }
            UnsafeNativeMethods.IDispatchEx    dispatchEx         = null;
            UnsafeNativeMethods.IHTMLDocument2 nativeHTMLDocument = this.NativeHTMLDocument;
            if (nativeHTMLDocument != null)
            {
                dispatchEx = (nativeHTMLDocument.GetScript() as UnsafeNativeMethods.IDispatchEx);
            }
            Uri source = this.Source;

            if (source != null)
            {
                SecurityHelper.DemandWebPermission(source);
            }
            if (nativeHTMLDocument != null)
            {
                string url = nativeHTMLDocument.GetUrl();
                if (string.CompareOrdinal(url, this.AxIWebBrowser2.LocationURL) != 0)
                {
                    SecurityHelper.DemandWebPermission(new Uri(url, UriKind.Absolute));
                }
            }
            object result = null;

            if (dispatchEx != null)
            {
                NativeMethods.DISPPARAMS dispparams = new NativeMethods.DISPPARAMS();
                dispparams.rgvarg = IntPtr.Zero;
                try
                {
                    Guid     empty     = Guid.Empty;
                    string[] rgszNames = new string[]
                    {
                        scriptName
                    };
                    int[] array = new int[]
                    {
                        -1
                    };
                    dispatchEx.GetIDsOfNames(ref empty, rgszNames, 1, Thread.CurrentThread.CurrentCulture.LCID, array).ThrowIfFailed();
                    if (args != null)
                    {
                        Array.Reverse(args);
                    }
                    dispparams.rgvarg            = ((args == null) ? IntPtr.Zero : UnsafeNativeMethods.ArrayToVARIANTHelper.ArrayToVARIANTVector(args));
                    dispparams.cArgs             = (uint)((args == null) ? 0 : args.Length);
                    dispparams.rgdispidNamedArgs = IntPtr.Zero;
                    dispparams.cNamedArgs        = 0U;
                    dispatchEx.InvokeEx(array[0], Thread.CurrentThread.CurrentCulture.LCID, 1, dispparams, out result, new NativeMethods.EXCEPINFO(), null).ThrowIfFailed();
                    return(result);
                }
                finally
                {
                    if (dispparams.rgvarg != IntPtr.Zero)
                    {
                        UnsafeNativeMethods.ArrayToVARIANTHelper.FreeVARIANTVector(dispparams.rgvarg, args.Length);
                    }
                }
            }
            throw new InvalidOperationException(SR.Get("CannotInvokeScript"));
        }