Beispiel #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);
        }
Beispiel #2
0
        private void HandleTaskbarListError(HRESULT hr)
        {
            if (hr.Failed)
            {
                // Even if some of the taskbar methods get this error it doesn't mean that all of them will.
                // They aren't all implemented with SendMessageTimeout, and unfortunately the ITaskbarList3 API inconsistently
                // exposes that implementation detail.
                if (hr == (HRESULT)Win32Error.ERROR_TIMEOUT)
                {
                    // Explorer appears to be busy.  Post back to the Window to try again.
                    if (TraceShell.IsEnabled)
                    {
                        TraceShell.Trace(TraceEventType.Error, TraceShell.ExplorerTaskbarTimeout);
                        TraceShell.Trace(TraceEventType.Warning, TraceShell.ExplorerTaskbarRetrying);
                    }

                    // Explorer being hung should be a transient issue.  Post back to apply the full TaskbarItemInfo.
                    _taskbarRetryTimer.Start();
                }
                else if (hr == (HRESULT)Win32Error.ERROR_INVALID_WINDOW_HANDLE)
                {
                    // We'll get this when Explorer's not running.  This means there's no Shell to integrate with.
                    if (TraceShell.IsEnabled)
                    {
                        TraceShell.Trace(TraceEventType.Warning, TraceShell.ExplorerTaskbarNotRunning);
                    }
                    // If this is a transient condition then we'll get a WM_TASKBARBUTTONCREATED when Explorer comes
                    // back and the taskbar button gets created again, at which point we'll rehook.
                    // In the meantime, just stop trying since there's no reasonable expectation of recovery.
                    Utilities.SafeRelease(ref _taskbarList);
                }
                else
                {
                    // That covers the troublesome errors that we know how to handle.
                    // For anything else we'll ignore the error and count on a subsequent update to correct the state.
                    if (TraceShell.IsEnabled)
                    {
                        TraceShell.Trace(TraceEventType.Error, TraceShell.NativeTaskbarError(hr.ToString()));
                    }
                }
            }
        }