Code:
/ 4.0 / 4.0 / untmp / 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.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- ColumnPropertiesGroup.cs
- StringCollection.cs
- ApplicationDirectoryMembershipCondition.cs
- ProgressBarAutomationPeer.cs
- shaper.cs
- ThreadStartException.cs
- WpfGeneratedKnownProperties.cs
- SizeIndependentAnimationStorage.cs
- TCPClient.cs
- ConsoleCancelEventArgs.cs
- DoubleAnimationUsingKeyFrames.cs
- EncodingInfo.cs
- CertificateElement.cs
- SmtpTransport.cs
- Decorator.cs
- SecuritySessionServerSettings.cs
- Size.cs
- CollectionCodeDomSerializer.cs
- TimeoutValidationAttribute.cs
- elementinformation.cs
- ImageFormat.cs
- TableColumnCollectionInternal.cs
- AccessDataSource.cs
- SessionStateItemCollection.cs
- MatrixCamera.cs
- GeneralTransform2DTo3D.cs
- LowerCaseStringConverter.cs
- BlurEffect.cs
- HttpListenerRequest.cs
- SqlBulkCopyColumnMappingCollection.cs
- HttpFileCollection.cs
- StrokeNodeOperations2.cs
- CachedFontFamily.cs
- ClientUrlResolverWrapper.cs
- XpsResourceDictionary.cs
- SmtpNetworkElement.cs
- FatalException.cs
- FragmentQueryKB.cs
- Matrix.cs
- ServiceOperationInvoker.cs
- BlurBitmapEffect.cs
- ProfileGroupSettings.cs
- odbcmetadatacollectionnames.cs
- DesignerSerializationOptionsAttribute.cs
- TextContainer.cs
- PerformanceCounterLib.cs
- GlobalId.cs
- EditorBrowsableAttribute.cs
- DbQueryCommandTree.cs
- VisualStates.cs
- PaintEvent.cs
- ValueTable.cs
- NullableIntSumAggregationOperator.cs
- XmlSecureResolver.cs
- Mappings.cs
- CreateUserWizardStep.cs
- CompilerParameters.cs
- WindowsEditBox.cs
- ToolStripDropDown.cs
- XPathSingletonIterator.cs
- configsystem.cs
- SqlPersonalizationProvider.cs
- VirtualPathUtility.cs
- DataControlField.cs
- GPStream.cs
- DefaultObjectMappingItemCollection.cs
- RegistryDataKey.cs
- NativeMethodsCLR.cs
- Domain.cs
- AudioStateChangedEventArgs.cs
- SqlServices.cs
- Process.cs
- SqlFlattener.cs
- sqlmetadatafactory.cs
- CommandManager.cs
- PropertyReference.cs
- ColumnBinding.cs
- AnimationClockResource.cs
- Common.cs
- ApplicationServicesHostFactory.cs
- Brush.cs
- ProfileManager.cs
- HostExecutionContextManager.cs
- SourceFileInfo.cs
- TextSpan.cs
- MimeMapping.cs
- Control.cs
- MarkupCompiler.cs
- WebServiceTypeData.cs
- TextEditorSelection.cs
- SynchronizedPool.cs
- ControlPager.cs
- _ListenerAsyncResult.cs
- ExceptionWrapper.cs
- SafeEventLogWriteHandle.cs
- SqlFormatter.cs
- ProgressChangedEventArgs.cs
- LoginCancelEventArgs.cs
- DelegatingConfigHost.cs
- InkCanvasAutomationPeer.cs