OleCmdHelper.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Framework / MS / Internal / AppModel / OleCmdHelper.cs / 1305600 / OleCmdHelper.cs

                            //---------------------------------------------------------------------------- 
//
// 
//    Copyright (C) Microsoft Corporation.  All rights reserved.
//  
//
// Description: 
//          This is a helper class used for interop to process the 
//          IOleCommandTarget calls in browser hosting scenario
// 
// History:
//  06/09/03: kusumav     Moved from Application.cs to separate file.
//
//--------------------------------------------------------------------------- 

using System; 
using System.Collections; 
using System.Diagnostics;
using System.Runtime.InteropServices; 

using System.Windows.Threading;
using System.Windows;
using System.Security; 
using System.Security.Permissions;
using System.Windows.Input; 
using System.Windows.Interop; 
using System.Windows.Navigation;
using System.Windows.Controls; 

using MS.Internal.Documents;                               // DocumentApplicationDocumentViewer
using MS.Internal.PresentationFramework;                   // SecurityHelper
using MS.Internal.KnownBoxes; 
using MS.Win32;
 
namespace MS.Internal.AppModel 
{
    #region OleCmdHelper class 
    // 
    // OleCmd helper class for processing IOleCommandTarget calls in browser hosting scenario
    // 
    internal sealed class OleCmdHelper : MarshalByRefObject 
    {
        internal const int 
            OLECMDERR_E_NOTSUPPORTED = unchecked((int)0x80040100), 
            OLECMDERR_E_DISABLED     = unchecked((int)0x80040101),
            OLECMDERR_E_UNKNOWNGROUP = unchecked((int)0x80040104); 
        internal const uint CommandUnsupported = 0;
        internal const uint CommandEnabled = (uint)(UnsafeNativeMethods.OLECMDF.OLECMDF_ENABLED | UnsafeNativeMethods.OLECMDF.OLECMDF_SUPPORTED);
        internal const uint CommandDisabled = (uint)UnsafeNativeMethods.OLECMDF.OLECMDF_SUPPORTED;
 
        // IMPORTANT: Keep this in [....] with wcp\host\inc\hostservices.idl
        internal static readonly Guid CGID_ApplicationCommands = new Guid(0xebbc8a63, 0x8559, 0x4892, 0x97, 0xa8, 0x31, 0xe9, 0xb0, 0xe9, 0x85, 0x91); 
        internal static readonly Guid CGID_EditingCommands = new Guid(0xc77ce45, 0xd1c, 0x4f2a, 0xb2, 0x93, 0xed, 0xd5, 0xe2, 0x7e, 0xba, 0x47); 

        internal OleCmdHelper() 
        {
        }

        ///  
        ///     Critical: This code calls into _DoqueryStatus
        ///  
        ///  
        /// The native code passes queries here only for the recognized command groups:
        /// standard (NULL), ApplicaitonCommands, EditingCommands. 
        /// 
        [SecurityCritical]
        internal void QueryStatus(Guid guidCmdGroup, uint cmdId, ref uint flags)
        { 
            /***IMPORTANT:
              Make sure to return allowed and appropriate values according to the specification of 
              IOleCommandTarget::QueryStatus(). In particular: 
                - OLECMDF_SUPPORTED without OLECMDF_ENABLED should not be blindly returned for
                    unrecognized commands. 
                - Some code in IE treats OLECMDERR_E_xxx differently from generic failures.
                - E_NOTIMPL is not an acceptable return value.
            */
 
            if (Application.Current == null || Application.IsShuttingDown == true)
            { 
                Marshal.ThrowExceptionForHR(NativeMethods.E_FAIL); 
            }
 
            // Get values from mapping here else mark them as disabled ==>
            // i.e "supported but not enabled" and is the equivalent of disabled since
            // there is no explicit "disabled" OLECMD flag
 
            IDictionary oleCmdMappingTable = GetOleCmdMappingTable(guidCmdGroup);
            if (oleCmdMappingTable == null) 
            { 
                Marshal.ThrowExceptionForHR(OleCmdHelper.OLECMDERR_E_UNKNOWNGROUP);
            } 
            CommandWithArgument command = oleCmdMappingTable[cmdId] as CommandWithArgument;
            if (command == null)
            {
                flags = CommandUnsupported; 
                return;
            } 
            // Go through the Dispatcher in order to use its SynchronizationContext and also 
            // so that any application exception caused during event routing is reported via
            // Dispatcher.UnhandledException. 
            // The above code is not in the callback, because it throws, and we don't want the
            // application to get these exceptions. (The COM Interop layer turns them into HRESULTs.)
            bool enabled = (bool)Application.Current.Dispatcher.Invoke(
                DispatcherPriority.Send, new DispatcherOperationCallback(QueryEnabled), command); 
            flags = enabled ? CommandEnabled : CommandDisabled;
        } 
 
        /// 
        ///     Critical: Calls the critical CommandWithArgument.QueryEnabled(). 
        /// 
        [SecurityCritical]
        private object QueryEnabled(object command)
        { 
            if (Application.Current.MainWindow == null)
                return false; 
            IInputElement target = FocusManager.GetFocusedElement(Application.Current.MainWindow); 
            if (target == null)
            { 
                // This will always succeed because Window is IInputElement
                target = (IInputElement)Application.Current.MainWindow;
            }
            return BooleanBoxes.Box(((CommandWithArgument)command).QueryEnabled(target, null)); 
        }
 
        ///  
        ///     Critical: This code calls into ExecCommandCallback helper
        ///  
        /// 
        /// The native code passes here only commands of the recognized command groups:
        /// standard (NULL), ApplicaitonCommands, EditingCommands.
        ///  
        [SecurityCritical]
        internal void ExecCommand(Guid guidCmdGroup, uint commandId, object arg) 
        { 
            if (Application.Current == null || Application.IsShuttingDown == true)
            { 
                Marshal.ThrowExceptionForHR(NativeMethods.E_FAIL);
            }

            int hresult = (int)Application.Current.Dispatcher.Invoke( 
                DispatcherPriority.Send,
                new DispatcherOperationCallback(ExecCommandCallback), 
                new object[] { guidCmdGroup, commandId, arg }); 
            // Note: ExecCommandCallback() returns an HRESULT instead of throwing for the reason
            // explained in QueryStatus(). 
            if(hresult < 0)
            {
                Marshal.ThrowExceptionForHR(hresult);
            } 
        }
 
        ///  
        ///    Critical:This API calls into Execute
        ///  
        [SecurityCritical]
        private object ExecCommandCallback(object arguments)
        {
            object[] args = (object[])arguments; 
            Invariant.Assert(args.Length == 3);
            Guid guidCmdGroup = (Guid)args[0]; 
            uint commandId = (uint)args[1]; 
            object arg = args[2];
 
            IDictionary oleCmdMappingTable = GetOleCmdMappingTable(guidCmdGroup);
            if (oleCmdMappingTable == null)
                return OLECMDERR_E_UNKNOWNGROUP;
            CommandWithArgument command = oleCmdMappingTable[commandId] as CommandWithArgument; 
            if (command == null)
                return OLECMDERR_E_NOTSUPPORTED; 
 
            if (Application.Current.MainWindow == null)
                return OLECMDERR_E_DISABLED; 
            IInputElement target = FocusManager.GetFocusedElement(Application.Current.MainWindow);
            if (target == null)
            {
                // This will always succeed because Window is IInputElement 
                target = (IInputElement)Application.Current.MainWindow;
            } 
            return command.Execute(target, arg) ? NativeMethods.S_OK : OLECMDERR_E_DISABLED; 
        }
 
        /// 
        ///    Critical:This API accesses the commandmapping table and returns it
        ///    TreatAsSafe: It returns a copy which is safe
        ///  
        [SecurityCritical, SecurityTreatAsSafe]
        private IDictionary GetOleCmdMappingTable(Guid guidCmdGroup) 
        { 
            IDictionary mappingTable = null;
 
            if (guidCmdGroup.Equals(CGID_ApplicationCommands))
            {
                EnsureApplicationCommandsTable();
                mappingTable = _applicationCommandsMappingTable.Value; 
            }
            else if(guidCmdGroup.Equals(Guid.Empty)) 
            { 
                EnsureOleCmdMappingTable();
                mappingTable = _oleCmdMappingTable.Value; 
            }
            else if (guidCmdGroup.Equals(CGID_EditingCommands))
            {
                EnsureEditingCommandsTable(); 
                mappingTable = _editingCommandsMappingTable.Value;
            } 
 
            return mappingTable;
        } 
        /// 
        ///     Critical: This code initializes the OleCmdMappingTable which is a critical for
        ///     set data structure
        ///     TreatAsSafe: All the values that it adds are predefined handlers in this class 
        ///     no external values
        ///  
        [SecurityCritical,SecurityTreatAsSafe] 
        private void EnsureOleCmdMappingTable()
        { 
            if (_oleCmdMappingTable.Value == null)
            {
                _oleCmdMappingTable.Value = new SortedList(10);
 
                //Add applevel commands here
                _oleCmdMappingTable.Value.Add((uint)UnsafeNativeMethods.OLECMDID.OLECMDID_SAVE, new CommandWithArgument(ApplicationCommands.Save)); 
                _oleCmdMappingTable.Value.Add((uint)UnsafeNativeMethods.OLECMDID.OLECMDID_SAVEAS, new CommandWithArgument(ApplicationCommands.SaveAs)); 
                _oleCmdMappingTable.Value.Add((uint)UnsafeNativeMethods.OLECMDID.OLECMDID_PRINT, new CommandWithArgument(ApplicationCommands.Print));
                _oleCmdMappingTable.Value.Add((uint)UnsafeNativeMethods.OLECMDID.OLECMDID_CUT, new CommandWithArgument(ApplicationCommands.Cut)); 
                _oleCmdMappingTable.Value.Add((uint)UnsafeNativeMethods.OLECMDID.OLECMDID_COPY, new CommandWithArgument(ApplicationCommands.Copy));
                _oleCmdMappingTable.Value.Add((uint)UnsafeNativeMethods.OLECMDID.OLECMDID_PASTE, new CommandWithArgument(ApplicationCommands.Paste));
                _oleCmdMappingTable.Value.Add((uint)UnsafeNativeMethods.OLECMDID.OLECMDID_PROPERTIES, new CommandWithArgument(ApplicationCommands.Properties));
 
                //Set the Enabled property of Stop and Refresh commands correctly
                _oleCmdMappingTable.Value.Add((uint)UnsafeNativeMethods.OLECMDID.OLECMDID_REFRESH, new CommandWithArgument(NavigationCommands.Refresh)); 
                _oleCmdMappingTable.Value.Add((uint)UnsafeNativeMethods.OLECMDID.OLECMDID_STOP, new CommandWithArgument(NavigationCommands.BrowseStop)); 
            }
        } 

        /// 
        ///     Critical: This code initializes the OleCmdMappingTable which is a critical for
        ///     set data structure 
        ///     TreatAsSafe: All the values that it adds are predefined handlers in this class
        ///     no external values 
        ///  
        [SecurityCritical, SecurityTreatAsSafe]
        private void EnsureApplicationCommandsTable() 
        {
            if (_applicationCommandsMappingTable.Value == null)
            {
                /* we want to possible add 26 entries, so the capacity should be 
                 * 26/0.72 = 19 for default of 1.0 load factor*/
                _applicationCommandsMappingTable.Value = new Hashtable(19); 
 
                //Add applevel commands here
                // Note: The keys are added as uint type so that the default container comparer works 
                // when we try to look up a command by a uint cmdid.
                _applicationCommandsMappingTable.Value.Add((uint)AppCommands.Edit_Cut, new CommandWithArgument(ApplicationCommands.Cut));
                _applicationCommandsMappingTable.Value.Add((uint)AppCommands.Edit_Copy, new CommandWithArgument(ApplicationCommands.Copy));
                _applicationCommandsMappingTable.Value.Add((uint)AppCommands.Edit_Paste, new CommandWithArgument(ApplicationCommands.Paste)); 
                _applicationCommandsMappingTable.Value.Add((uint)AppCommands.Edit_SelectAll, new CommandWithArgument(ApplicationCommands.SelectAll));
                _applicationCommandsMappingTable.Value.Add((uint)AppCommands.Edit_Find, new CommandWithArgument(ApplicationCommands.Find)); 
 
                // Add standard navigation commands
                _applicationCommandsMappingTable.Value.Add((uint)AppCommands.View_Refresh, new CommandWithArgument(NavigationCommands.Refresh)); 
                _applicationCommandsMappingTable.Value.Add((uint)AppCommands.View_Stop, new CommandWithArgument(NavigationCommands.BrowseStop));

                // add document viewer commands
                _applicationCommandsMappingTable.Value.Add((uint)AppCommands.Edit_Digitalsignatures_SignDocument, new CommandWithArgument(DocumentApplicationDocumentViewer.Sign)); 
                _applicationCommandsMappingTable.Value.Add((uint)AppCommands.Edit_Digitalsignatures_RequestSignature, new CommandWithArgument(DocumentApplicationDocumentViewer.RequestSigners));
                _applicationCommandsMappingTable.Value.Add((uint)AppCommands.Edit_Digitalsignatures_ViewSignature, new CommandWithArgument(DocumentApplicationDocumentViewer.ShowSignatureSummary)); 
                _applicationCommandsMappingTable.Value.Add((uint)AppCommands.Edit_Permission_Set, new CommandWithArgument(DocumentApplicationDocumentViewer.ShowRMPublishingUI)); 
                _applicationCommandsMappingTable.Value.Add((uint)AppCommands.Edit_Permission_View, new CommandWithArgument(DocumentApplicationDocumentViewer.ShowRMPermissions));
                _applicationCommandsMappingTable.Value.Add((uint)AppCommands.Edit_Permission_Restrict, new CommandWithArgument(DocumentApplicationDocumentViewer.ShowRMCredentialManager)); 
                _applicationCommandsMappingTable.Value.Add((uint)AppCommands.View_Zoom_In, new CommandWithArgument(NavigationCommands.IncreaseZoom));
                _applicationCommandsMappingTable.Value.Add((uint)AppCommands.View_Zoom_Out, new CommandWithArgument(NavigationCommands.DecreaseZoom));
                _applicationCommandsMappingTable.Value.Add((uint)AppCommands.View_Zoom_400, new CommandWithArgument(NavigationCommands.Zoom, 400));
                _applicationCommandsMappingTable.Value.Add((uint)AppCommands.View_Zoom_250, new CommandWithArgument(NavigationCommands.Zoom, 250)); 
                _applicationCommandsMappingTable.Value.Add((uint)AppCommands.View_Zoom_150, new CommandWithArgument(NavigationCommands.Zoom, 150));
                _applicationCommandsMappingTable.Value.Add((uint)AppCommands.View_Zoom_100, new CommandWithArgument(NavigationCommands.Zoom, 100)); 
                _applicationCommandsMappingTable.Value.Add((uint)AppCommands.View_Zoom_75, new CommandWithArgument(NavigationCommands.Zoom, 75)); 
                _applicationCommandsMappingTable.Value.Add((uint)AppCommands.View_Zoom_50, new CommandWithArgument(NavigationCommands.Zoom, 50));
                _applicationCommandsMappingTable.Value.Add((uint)AppCommands.View_Zoom_25, new CommandWithArgument(NavigationCommands.Zoom, 25)); 
                _applicationCommandsMappingTable.Value.Add((uint)AppCommands.View_Zoom_PageWidth, new CommandWithArgument(DocumentViewer.FitToWidthCommand));
                _applicationCommandsMappingTable.Value.Add((uint)AppCommands.View_Zoom_WholePage, new CommandWithArgument(DocumentViewer.FitToHeightCommand));
                _applicationCommandsMappingTable.Value.Add((uint)AppCommands.View_Zoom_TwoPages, new CommandWithArgument(DocumentViewer.FitToMaxPagesAcrossCommand, 2));
                _applicationCommandsMappingTable.Value.Add((uint)AppCommands.View_Zoom_Thumbnails, new CommandWithArgument(DocumentViewer.ViewThumbnailsCommand)); 
            }
        } 
 
        /// 
        /// Critical: Initializes _editingCommandsMappingTable, which is a critical for set. 
        /// TreatAsSafe: Only predefined commands are used. EditingCommands are enabled in partial trust.
        /// 
        [SecurityCritical, SecurityTreatAsSafe]
        private void EnsureEditingCommandsTable() 
        {
            if (_editingCommandsMappingTable.Value == null) 
            { 
                _editingCommandsMappingTable.Value = new SortedList(2);
                // Note: The keys are added as uint type so that the default container comparer works 
                // when we try to look up a command by a uint cmdid.
                _editingCommandsMappingTable.Value.Add((uint)EditingCommandIds.Backspace,
                    new CommandWithArgument(System.Windows.Documents.EditingCommands.Backspace));
                _editingCommandsMappingTable.Value.Add((uint)EditingCommandIds.Delete, 
                    new CommandWithArgument(System.Windows.Documents.EditingCommands.Delete));
            } 
        } 

        private SecurityCriticalDataForSet _oleCmdMappingTable; 
        private SecurityCriticalDataForSet _applicationCommandsMappingTable;
        private SecurityCriticalDataForSet _editingCommandsMappingTable;
    }
    #endregion OleCmdHelper class 

    #region CommandAndArgument class 
 
    /// 
    /// This wrapper class helps store default arguments for commands. 
    /// The primary scenario for this class is the Zoom command where we
    /// have multiple menu items and want to fire a single event with an
    /// argument.  We cannot attach an argument value to the native menu
    /// item so when we do the translation we add it. 
    /// 
    internal class CommandWithArgument 
    { 
        /// 
        ///     Critical: This can be used to spoof paste command 
        /// 
        [SecurityCritical]
        public CommandWithArgument(RoutedCommand command) : this(command, null)
        { } 

        ///  
        ///     Critical: This can be used to spoof paste command 
        /// 
        [SecurityCritical] 
        public CommandWithArgument(RoutedCommand command, object argument)
        {
            _command = new SecurityCriticalDataForSet(command);
            _argument = argument; 
        }
 
        ///  
        ///    Critical:This API calls into ExecuteCore and CriticalCanExecute
        ///  
        [SecurityCritical]
        public bool Execute(IInputElement target, object argument)
        {
            if (argument == null) 
            {
                argument = _argument; 
            } 

            // ISecureCommand is used to enforce user-initiated invocation. Cut, Copy and Paste 
            // are marked as such. See ApplicationCommands.GetRequiredPermissions.
            if (_command.Value is ISecureCommand)
            {
                bool unused; 
                if (_command.Value.CriticalCanExecute(argument, target, /* trusted: */ true, out unused))
                { 
                    _command.Value.ExecuteCore(argument, target, /* userInitiated: */ true); 
                    return true;
                } 
                return false;
            }
            if (_command.Value.CanExecute(argument, target))
            { 
                _command.Value.Execute(argument, target);
                return true; 
            } 
            return false;
        } 


        /// 
        ///     Critical: This code calls into Routedcommand.QueryStatus 
        ///     with a trusted bit, that can be used to cause an elevation.
        ///  
        [SecurityCritical] 
        public bool QueryEnabled(IInputElement target, object argument)
        { 
            if (argument == null)
            {
                argument = _argument;
            } 

            // ISecureCommand is used to enforce user-initiated invocation. Cut, Copy and Paste 
            // are marked as such. See ApplicationCommands.GetRequiredPermissions. 
            if (_command.Value is ISecureCommand)
            { 
                bool unused;
                return _command.Value.CriticalCanExecute(argument, target, /* trusted: */ true, out unused);
            }
            return _command.Value.CanExecute(argument, target); 

        } 
 
        public RoutedCommand Command
        { 
            get
            {
                return _command.Value;
            } 
        }
 
        private object _argument; 

        ///  
        ///     Critical: This data is critical for set since it is used to make a security decision
        /// 
        private SecurityCriticalDataForSet _command;
    } 

    #endregion 
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
//---------------------------------------------------------------------------- 
//
// 
//    Copyright (C) Microsoft Corporation.  All rights reserved.
//  
//
// Description: 
//          This is a helper class used for interop to process the 
//          IOleCommandTarget calls in browser hosting scenario
// 
// History:
//  06/09/03: kusumav     Moved from Application.cs to separate file.
//
//--------------------------------------------------------------------------- 

using System; 
using System.Collections; 
using System.Diagnostics;
using System.Runtime.InteropServices; 

using System.Windows.Threading;
using System.Windows;
using System.Security; 
using System.Security.Permissions;
using System.Windows.Input; 
using System.Windows.Interop; 
using System.Windows.Navigation;
using System.Windows.Controls; 

using MS.Internal.Documents;                               // DocumentApplicationDocumentViewer
using MS.Internal.PresentationFramework;                   // SecurityHelper
using MS.Internal.KnownBoxes; 
using MS.Win32;
 
namespace MS.Internal.AppModel 
{
    #region OleCmdHelper class 
    // 
    // OleCmd helper class for processing IOleCommandTarget calls in browser hosting scenario
    // 
    internal sealed class OleCmdHelper : MarshalByRefObject 
    {
        internal const int 
            OLECMDERR_E_NOTSUPPORTED = unchecked((int)0x80040100), 
            OLECMDERR_E_DISABLED     = unchecked((int)0x80040101),
            OLECMDERR_E_UNKNOWNGROUP = unchecked((int)0x80040104); 
        internal const uint CommandUnsupported = 0;
        internal const uint CommandEnabled = (uint)(UnsafeNativeMethods.OLECMDF.OLECMDF_ENABLED | UnsafeNativeMethods.OLECMDF.OLECMDF_SUPPORTED);
        internal const uint CommandDisabled = (uint)UnsafeNativeMethods.OLECMDF.OLECMDF_SUPPORTED;
 
        // IMPORTANT: Keep this in [....] with wcp\host\inc\hostservices.idl
        internal static readonly Guid CGID_ApplicationCommands = new Guid(0xebbc8a63, 0x8559, 0x4892, 0x97, 0xa8, 0x31, 0xe9, 0xb0, 0xe9, 0x85, 0x91); 
        internal static readonly Guid CGID_EditingCommands = new Guid(0xc77ce45, 0xd1c, 0x4f2a, 0xb2, 0x93, 0xed, 0xd5, 0xe2, 0x7e, 0xba, 0x47); 

        internal OleCmdHelper() 
        {
        }

        ///  
        ///     Critical: This code calls into _DoqueryStatus
        ///  
        ///  
        /// The native code passes queries here only for the recognized command groups:
        /// standard (NULL), ApplicaitonCommands, EditingCommands. 
        /// 
        [SecurityCritical]
        internal void QueryStatus(Guid guidCmdGroup, uint cmdId, ref uint flags)
        { 
            /***IMPORTANT:
              Make sure to return allowed and appropriate values according to the specification of 
              IOleCommandTarget::QueryStatus(). In particular: 
                - OLECMDF_SUPPORTED without OLECMDF_ENABLED should not be blindly returned for
                    unrecognized commands. 
                - Some code in IE treats OLECMDERR_E_xxx differently from generic failures.
                - E_NOTIMPL is not an acceptable return value.
            */
 
            if (Application.Current == null || Application.IsShuttingDown == true)
            { 
                Marshal.ThrowExceptionForHR(NativeMethods.E_FAIL); 
            }
 
            // Get values from mapping here else mark them as disabled ==>
            // i.e "supported but not enabled" and is the equivalent of disabled since
            // there is no explicit "disabled" OLECMD flag
 
            IDictionary oleCmdMappingTable = GetOleCmdMappingTable(guidCmdGroup);
            if (oleCmdMappingTable == null) 
            { 
                Marshal.ThrowExceptionForHR(OleCmdHelper.OLECMDERR_E_UNKNOWNGROUP);
            } 
            CommandWithArgument command = oleCmdMappingTable[cmdId] as CommandWithArgument;
            if (command == null)
            {
                flags = CommandUnsupported; 
                return;
            } 
            // Go through the Dispatcher in order to use its SynchronizationContext and also 
            // so that any application exception caused during event routing is reported via
            // Dispatcher.UnhandledException. 
            // The above code is not in the callback, because it throws, and we don't want the
            // application to get these exceptions. (The COM Interop layer turns them into HRESULTs.)
            bool enabled = (bool)Application.Current.Dispatcher.Invoke(
                DispatcherPriority.Send, new DispatcherOperationCallback(QueryEnabled), command); 
            flags = enabled ? CommandEnabled : CommandDisabled;
        } 
 
        /// 
        ///     Critical: Calls the critical CommandWithArgument.QueryEnabled(). 
        /// 
        [SecurityCritical]
        private object QueryEnabled(object command)
        { 
            if (Application.Current.MainWindow == null)
                return false; 
            IInputElement target = FocusManager.GetFocusedElement(Application.Current.MainWindow); 
            if (target == null)
            { 
                // This will always succeed because Window is IInputElement
                target = (IInputElement)Application.Current.MainWindow;
            }
            return BooleanBoxes.Box(((CommandWithArgument)command).QueryEnabled(target, null)); 
        }
 
        ///  
        ///     Critical: This code calls into ExecCommandCallback helper
        ///  
        /// 
        /// The native code passes here only commands of the recognized command groups:
        /// standard (NULL), ApplicaitonCommands, EditingCommands.
        ///  
        [SecurityCritical]
        internal void ExecCommand(Guid guidCmdGroup, uint commandId, object arg) 
        { 
            if (Application.Current == null || Application.IsShuttingDown == true)
            { 
                Marshal.ThrowExceptionForHR(NativeMethods.E_FAIL);
            }

            int hresult = (int)Application.Current.Dispatcher.Invoke( 
                DispatcherPriority.Send,
                new DispatcherOperationCallback(ExecCommandCallback), 
                new object[] { guidCmdGroup, commandId, arg }); 
            // Note: ExecCommandCallback() returns an HRESULT instead of throwing for the reason
            // explained in QueryStatus(). 
            if(hresult < 0)
            {
                Marshal.ThrowExceptionForHR(hresult);
            } 
        }
 
        ///  
        ///    Critical:This API calls into Execute
        ///  
        [SecurityCritical]
        private object ExecCommandCallback(object arguments)
        {
            object[] args = (object[])arguments; 
            Invariant.Assert(args.Length == 3);
            Guid guidCmdGroup = (Guid)args[0]; 
            uint commandId = (uint)args[1]; 
            object arg = args[2];
 
            IDictionary oleCmdMappingTable = GetOleCmdMappingTable(guidCmdGroup);
            if (oleCmdMappingTable == null)
                return OLECMDERR_E_UNKNOWNGROUP;
            CommandWithArgument command = oleCmdMappingTable[commandId] as CommandWithArgument; 
            if (command == null)
                return OLECMDERR_E_NOTSUPPORTED; 
 
            if (Application.Current.MainWindow == null)
                return OLECMDERR_E_DISABLED; 
            IInputElement target = FocusManager.GetFocusedElement(Application.Current.MainWindow);
            if (target == null)
            {
                // This will always succeed because Window is IInputElement 
                target = (IInputElement)Application.Current.MainWindow;
            } 
            return command.Execute(target, arg) ? NativeMethods.S_OK : OLECMDERR_E_DISABLED; 
        }
 
        /// 
        ///    Critical:This API accesses the commandmapping table and returns it
        ///    TreatAsSafe: It returns a copy which is safe
        ///  
        [SecurityCritical, SecurityTreatAsSafe]
        private IDictionary GetOleCmdMappingTable(Guid guidCmdGroup) 
        { 
            IDictionary mappingTable = null;
 
            if (guidCmdGroup.Equals(CGID_ApplicationCommands))
            {
                EnsureApplicationCommandsTable();
                mappingTable = _applicationCommandsMappingTable.Value; 
            }
            else if(guidCmdGroup.Equals(Guid.Empty)) 
            { 
                EnsureOleCmdMappingTable();
                mappingTable = _oleCmdMappingTable.Value; 
            }
            else if (guidCmdGroup.Equals(CGID_EditingCommands))
            {
                EnsureEditingCommandsTable(); 
                mappingTable = _editingCommandsMappingTable.Value;
            } 
 
            return mappingTable;
        } 
        /// 
        ///     Critical: This code initializes the OleCmdMappingTable which is a critical for
        ///     set data structure
        ///     TreatAsSafe: All the values that it adds are predefined handlers in this class 
        ///     no external values
        ///  
        [SecurityCritical,SecurityTreatAsSafe] 
        private void EnsureOleCmdMappingTable()
        { 
            if (_oleCmdMappingTable.Value == null)
            {
                _oleCmdMappingTable.Value = new SortedList(10);
 
                //Add applevel commands here
                _oleCmdMappingTable.Value.Add((uint)UnsafeNativeMethods.OLECMDID.OLECMDID_SAVE, new CommandWithArgument(ApplicationCommands.Save)); 
                _oleCmdMappingTable.Value.Add((uint)UnsafeNativeMethods.OLECMDID.OLECMDID_SAVEAS, new CommandWithArgument(ApplicationCommands.SaveAs)); 
                _oleCmdMappingTable.Value.Add((uint)UnsafeNativeMethods.OLECMDID.OLECMDID_PRINT, new CommandWithArgument(ApplicationCommands.Print));
                _oleCmdMappingTable.Value.Add((uint)UnsafeNativeMethods.OLECMDID.OLECMDID_CUT, new CommandWithArgument(ApplicationCommands.Cut)); 
                _oleCmdMappingTable.Value.Add((uint)UnsafeNativeMethods.OLECMDID.OLECMDID_COPY, new CommandWithArgument(ApplicationCommands.Copy));
                _oleCmdMappingTable.Value.Add((uint)UnsafeNativeMethods.OLECMDID.OLECMDID_PASTE, new CommandWithArgument(ApplicationCommands.Paste));
                _oleCmdMappingTable.Value.Add((uint)UnsafeNativeMethods.OLECMDID.OLECMDID_PROPERTIES, new CommandWithArgument(ApplicationCommands.Properties));
 
                //Set the Enabled property of Stop and Refresh commands correctly
                _oleCmdMappingTable.Value.Add((uint)UnsafeNativeMethods.OLECMDID.OLECMDID_REFRESH, new CommandWithArgument(NavigationCommands.Refresh)); 
                _oleCmdMappingTable.Value.Add((uint)UnsafeNativeMethods.OLECMDID.OLECMDID_STOP, new CommandWithArgument(NavigationCommands.BrowseStop)); 
            }
        } 

        /// 
        ///     Critical: This code initializes the OleCmdMappingTable which is a critical for
        ///     set data structure 
        ///     TreatAsSafe: All the values that it adds are predefined handlers in this class
        ///     no external values 
        ///  
        [SecurityCritical, SecurityTreatAsSafe]
        private void EnsureApplicationCommandsTable() 
        {
            if (_applicationCommandsMappingTable.Value == null)
            {
                /* we want to possible add 26 entries, so the capacity should be 
                 * 26/0.72 = 19 for default of 1.0 load factor*/
                _applicationCommandsMappingTable.Value = new Hashtable(19); 
 
                //Add applevel commands here
                // Note: The keys are added as uint type so that the default container comparer works 
                // when we try to look up a command by a uint cmdid.
                _applicationCommandsMappingTable.Value.Add((uint)AppCommands.Edit_Cut, new CommandWithArgument(ApplicationCommands.Cut));
                _applicationCommandsMappingTable.Value.Add((uint)AppCommands.Edit_Copy, new CommandWithArgument(ApplicationCommands.Copy));
                _applicationCommandsMappingTable.Value.Add((uint)AppCommands.Edit_Paste, new CommandWithArgument(ApplicationCommands.Paste)); 
                _applicationCommandsMappingTable.Value.Add((uint)AppCommands.Edit_SelectAll, new CommandWithArgument(ApplicationCommands.SelectAll));
                _applicationCommandsMappingTable.Value.Add((uint)AppCommands.Edit_Find, new CommandWithArgument(ApplicationCommands.Find)); 
 
                // Add standard navigation commands
                _applicationCommandsMappingTable.Value.Add((uint)AppCommands.View_Refresh, new CommandWithArgument(NavigationCommands.Refresh)); 
                _applicationCommandsMappingTable.Value.Add((uint)AppCommands.View_Stop, new CommandWithArgument(NavigationCommands.BrowseStop));

                // add document viewer commands
                _applicationCommandsMappingTable.Value.Add((uint)AppCommands.Edit_Digitalsignatures_SignDocument, new CommandWithArgument(DocumentApplicationDocumentViewer.Sign)); 
                _applicationCommandsMappingTable.Value.Add((uint)AppCommands.Edit_Digitalsignatures_RequestSignature, new CommandWithArgument(DocumentApplicationDocumentViewer.RequestSigners));
                _applicationCommandsMappingTable.Value.Add((uint)AppCommands.Edit_Digitalsignatures_ViewSignature, new CommandWithArgument(DocumentApplicationDocumentViewer.ShowSignatureSummary)); 
                _applicationCommandsMappingTable.Value.Add((uint)AppCommands.Edit_Permission_Set, new CommandWithArgument(DocumentApplicationDocumentViewer.ShowRMPublishingUI)); 
                _applicationCommandsMappingTable.Value.Add((uint)AppCommands.Edit_Permission_View, new CommandWithArgument(DocumentApplicationDocumentViewer.ShowRMPermissions));
                _applicationCommandsMappingTable.Value.Add((uint)AppCommands.Edit_Permission_Restrict, new CommandWithArgument(DocumentApplicationDocumentViewer.ShowRMCredentialManager)); 
                _applicationCommandsMappingTable.Value.Add((uint)AppCommands.View_Zoom_In, new CommandWithArgument(NavigationCommands.IncreaseZoom));
                _applicationCommandsMappingTable.Value.Add((uint)AppCommands.View_Zoom_Out, new CommandWithArgument(NavigationCommands.DecreaseZoom));
                _applicationCommandsMappingTable.Value.Add((uint)AppCommands.View_Zoom_400, new CommandWithArgument(NavigationCommands.Zoom, 400));
                _applicationCommandsMappingTable.Value.Add((uint)AppCommands.View_Zoom_250, new CommandWithArgument(NavigationCommands.Zoom, 250)); 
                _applicationCommandsMappingTable.Value.Add((uint)AppCommands.View_Zoom_150, new CommandWithArgument(NavigationCommands.Zoom, 150));
                _applicationCommandsMappingTable.Value.Add((uint)AppCommands.View_Zoom_100, new CommandWithArgument(NavigationCommands.Zoom, 100)); 
                _applicationCommandsMappingTable.Value.Add((uint)AppCommands.View_Zoom_75, new CommandWithArgument(NavigationCommands.Zoom, 75)); 
                _applicationCommandsMappingTable.Value.Add((uint)AppCommands.View_Zoom_50, new CommandWithArgument(NavigationCommands.Zoom, 50));
                _applicationCommandsMappingTable.Value.Add((uint)AppCommands.View_Zoom_25, new CommandWithArgument(NavigationCommands.Zoom, 25)); 
                _applicationCommandsMappingTable.Value.Add((uint)AppCommands.View_Zoom_PageWidth, new CommandWithArgument(DocumentViewer.FitToWidthCommand));
                _applicationCommandsMappingTable.Value.Add((uint)AppCommands.View_Zoom_WholePage, new CommandWithArgument(DocumentViewer.FitToHeightCommand));
                _applicationCommandsMappingTable.Value.Add((uint)AppCommands.View_Zoom_TwoPages, new CommandWithArgument(DocumentViewer.FitToMaxPagesAcrossCommand, 2));
                _applicationCommandsMappingTable.Value.Add((uint)AppCommands.View_Zoom_Thumbnails, new CommandWithArgument(DocumentViewer.ViewThumbnailsCommand)); 
            }
        } 
 
        /// 
        /// Critical: Initializes _editingCommandsMappingTable, which is a critical for set. 
        /// TreatAsSafe: Only predefined commands are used. EditingCommands are enabled in partial trust.
        /// 
        [SecurityCritical, SecurityTreatAsSafe]
        private void EnsureEditingCommandsTable() 
        {
            if (_editingCommandsMappingTable.Value == null) 
            { 
                _editingCommandsMappingTable.Value = new SortedList(2);
                // Note: The keys are added as uint type so that the default container comparer works 
                // when we try to look up a command by a uint cmdid.
                _editingCommandsMappingTable.Value.Add((uint)EditingCommandIds.Backspace,
                    new CommandWithArgument(System.Windows.Documents.EditingCommands.Backspace));
                _editingCommandsMappingTable.Value.Add((uint)EditingCommandIds.Delete, 
                    new CommandWithArgument(System.Windows.Documents.EditingCommands.Delete));
            } 
        } 

        private SecurityCriticalDataForSet _oleCmdMappingTable; 
        private SecurityCriticalDataForSet _applicationCommandsMappingTable;
        private SecurityCriticalDataForSet _editingCommandsMappingTable;
    }
    #endregion OleCmdHelper class 

    #region CommandAndArgument class 
 
    /// 
    /// This wrapper class helps store default arguments for commands. 
    /// The primary scenario for this class is the Zoom command where we
    /// have multiple menu items and want to fire a single event with an
    /// argument.  We cannot attach an argument value to the native menu
    /// item so when we do the translation we add it. 
    /// 
    internal class CommandWithArgument 
    { 
        /// 
        ///     Critical: This can be used to spoof paste command 
        /// 
        [SecurityCritical]
        public CommandWithArgument(RoutedCommand command) : this(command, null)
        { } 

        ///  
        ///     Critical: This can be used to spoof paste command 
        /// 
        [SecurityCritical] 
        public CommandWithArgument(RoutedCommand command, object argument)
        {
            _command = new SecurityCriticalDataForSet(command);
            _argument = argument; 
        }
 
        ///  
        ///    Critical:This API calls into ExecuteCore and CriticalCanExecute
        ///  
        [SecurityCritical]
        public bool Execute(IInputElement target, object argument)
        {
            if (argument == null) 
            {
                argument = _argument; 
            } 

            // ISecureCommand is used to enforce user-initiated invocation. Cut, Copy and Paste 
            // are marked as such. See ApplicationCommands.GetRequiredPermissions.
            if (_command.Value is ISecureCommand)
            {
                bool unused; 
                if (_command.Value.CriticalCanExecute(argument, target, /* trusted: */ true, out unused))
                { 
                    _command.Value.ExecuteCore(argument, target, /* userInitiated: */ true); 
                    return true;
                } 
                return false;
            }
            if (_command.Value.CanExecute(argument, target))
            { 
                _command.Value.Execute(argument, target);
                return true; 
            } 
            return false;
        } 


        /// 
        ///     Critical: This code calls into Routedcommand.QueryStatus 
        ///     with a trusted bit, that can be used to cause an elevation.
        ///  
        [SecurityCritical] 
        public bool QueryEnabled(IInputElement target, object argument)
        { 
            if (argument == null)
            {
                argument = _argument;
            } 

            // ISecureCommand is used to enforce user-initiated invocation. Cut, Copy and Paste 
            // are marked as such. See ApplicationCommands.GetRequiredPermissions. 
            if (_command.Value is ISecureCommand)
            { 
                bool unused;
                return _command.Value.CriticalCanExecute(argument, target, /* trusted: */ true, out unused);
            }
            return _command.Value.CanExecute(argument, target); 

        } 
 
        public RoutedCommand Command
        { 
            get
            {
                return _command.Value;
            } 
        }
 
        private object _argument; 

        ///  
        ///     Critical: This data is critical for set since it is used to make a security decision
        /// 
        private SecurityCriticalDataForSet _command;
    } 

    #endregion 
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK