Code:
/ DotNET / DotNET / 8.0 / untmp / WIN_WINDOWS / lh_tools_devdiv_wpf / Windows / wcp / Framework / MS / Internal / AppModel / OleCmdHelper.cs / 1 / 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: [....] 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, IOleCmdMappingService { 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 sync 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 path enables you to add arbitrary commands /// to a mapping table which is a critical resource /// [SecurityCritical] void IOleCmdMappingService.AddMapping(uint olecmd, RoutedCommand command) { _oleCmdMappingTable.Value[olecmd] = command; } event EventHandler IOleCmdMappingService.UpdatingMappingTable { add { _updateMappingTable += value; } remove { _updateMappingTable -= value; } } ////// 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)); //Ensure the mapping table is up-to-date taking into consideration //any navigations that may be changed the input manager (which is currently //per root, so top level navs will require us to reconstruct the table) UpdateMappingTable(_oleCmdMappingTable.Value); } } ////// 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)); //Ensure the mapping table is up-to-date taking into consideration //any navigations that may be changed the input manager (which is currently //per root, so top level navs will require us to reconstruct the table) UpdateMappingTable(_applicationCommandsMappingTable.Value); } } ////// 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)); } } ////// Critical - creates a command binding. Performs an elevation to register the Binding. /// [SecurityCritical] private void UpdateMappingTable(IDictionary mappingTable) { if (_updateMappingTable != null) { _updateMappingTable(this, EventArgs.Empty); } Window window = Application.Current.MainWindow; if (window != null) { window.InputBindings.Add(new KeyBinding(NavigationCommands.Refresh, Key.F5, ModifierKeys.Control)); foreach (CommandWithArgument command in mappingTable.Values) { CommandBinding commandBinding ; // // if this is a secure command - a demand will be performed at // registration of the command binding. // So we perform an assert. // Considered safe - as we're only allowing registration of the command ( e.g. paste) // ISecureCommand secCommand = command.Command as ISecureCommand; if ( secCommand != null ) { secCommand.UserInitiatedPermission.Assert(); } try { commandBinding = new CommandBinding(command.Command); } finally { if (secCommand != null) CodeAccessPermission.RevertAssert(); } if (command.Command == ApplicationCommands.Properties) { commandBinding.CanExecute += new CanExecuteRoutedEventHandler(OnPropertiesQueryEnabled); commandBinding.Executed += new ExecutedRoutedEventHandler(OnPropertiesCommand); } window.CommandBindings.Add(commandBinding); } } } ////// This is the method that gets called when ApplicationCommands.Properties ExecutedRoutedEventHandler get called. /// /// assumptions: /// It should only get called if we are hosted in browser. /// private void OnPropertiesQueryEnabled(object sender, CanExecuteRoutedEventArgs args) { //only hookup the Properties Command if we are hosted in browser and this is a container bool isContainer = Application.Current.MimeType == MimeType.Document; args.CanExecute = (BrowserInteropHelper.IsBrowserHosted && isContainer); } ////// This is the method that gets called when ApplicationCommands.PropertiesCommand /// CommandEventInvokeHandlers get called. /// /// assumptions: /// It should only get called if we are hosted in browser, and if we are /// hosting a container. We do nothing for EXEs /// private void OnPropertiesCommand(object sender, ExecutedRoutedEventArgs execArgs) { // todo: // Task: 40616: MetaData/Properties - View Document Properties // The plan for containers is to wire up a winforms dialog that can // show properties for a package. I recommend having Application // create a method that can be overridden by DocumentApplication // which can respond to this command. The call would look like: // // Application.OnPropertiesCommand(sender, execArgs); // // The Application implementation would do nothing, satisfying xapp. } private SecurityCriticalDataForSet_oleCmdMappingTable; private SecurityCriticalDataForSet _applicationCommandsMappingTable; private SecurityCriticalDataForSet _editingCommandsMappingTable; private EventHandler _updateMappingTable; } #endregion OleCmdHelper class #region IOleCmdMappingService interface internal interface IOleCmdMappingService { void AddMapping(uint olecmd, RoutedCommand command); event EventHandler UpdatingMappingTable; } #endregion IOleCmdMappingService interface #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; } if (_command.Value == ApplicationCommands.Paste || _command.Value == ApplicationCommands.Copy) { bool unused; if (_command.Value.CriticalCanExecute(argument, target, true, out unused)) { _command.Value.ExecuteCore(argument, target, 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; } if (_command.Value == ApplicationCommands.Paste) { bool unused; return _command.Value.CriticalCanExecute(argument, target, 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
- GeometryGroup.cs
- XmlSchemaSimpleContent.cs
- XmlCodeExporter.cs
- WmfPlaceableFileHeader.cs
- TextRunTypographyProperties.cs
- ResolvedKeyFrameEntry.cs
- AnimationClock.cs
- XamlFilter.cs
- Subset.cs
- NativeMethods.cs
- PlainXmlSerializer.cs
- Vector3D.cs
- CancellationHandler.cs
- LightweightEntityWrapper.cs
- SecureUICommand.cs
- DetailsViewInsertedEventArgs.cs
- XsdDateTime.cs
- documentsequencetextview.cs
- ProfilePropertySettingsCollection.cs
- WebBrowser.cs
- Point4DValueSerializer.cs
- ProfileParameter.cs
- SafeLibraryHandle.cs
- IntSecurity.cs
- PasswordRecovery.cs
- _ProxyRegBlob.cs
- EntityTransaction.cs
- DataGridViewCellCollection.cs
- DrawingAttributeSerializer.cs
- AnnotationAdorner.cs
- EdgeProfileValidation.cs
- DNS.cs
- ResXDataNode.cs
- SafeLibraryHandle.cs
- assemblycache.cs
- EdmScalarPropertyAttribute.cs
- XpsResource.cs
- MatrixConverter.cs
- RuleInfoComparer.cs
- CreateDataSourceDialog.cs
- HuffModule.cs
- SHA1.cs
- DataGridItem.cs
- RtfFormatStack.cs
- ListenerSessionConnection.cs
- ModelMemberCollection.cs
- ValidationHelpers.cs
- SplineKeyFrames.cs
- ScriptHandlerFactory.cs
- __ComObject.cs
- DefaultTraceListener.cs
- ArrayWithOffset.cs
- DbConnectionPoolGroup.cs
- TrackBarRenderer.cs
- ImageCollectionCodeDomSerializer.cs
- NumberFormatter.cs
- EditBehavior.cs
- CompleteWizardStep.cs
- SchemaImporterExtensionElement.cs
- File.cs
- DataGridViewRowHeaderCell.cs
- SecurityTokenValidationException.cs
- ConfigurationStrings.cs
- ReliableMessagingVersionConverter.cs
- DetailsViewModeEventArgs.cs
- localization.cs
- GcSettings.cs
- RsaKeyGen.cs
- DropDownList.cs
- FileFormatException.cs
- CapacityStreamGeometryContext.cs
- CollectionChangedEventManager.cs
- EntityModelSchemaGenerator.cs
- OutgoingWebResponseContext.cs
- DescendantQuery.cs
- TextElementEnumerator.cs
- UriTemplateMatch.cs
- AutoScrollHelper.cs
- BorderGapMaskConverter.cs
- AmbientProperties.cs
- Italic.cs
- HandledEventArgs.cs
- DataIdProcessor.cs
- ClassData.cs
- SimpleType.cs
- XPathNavigator.cs
- HtmlInputRadioButton.cs
- TemplatePropertyEntry.cs
- SelectedGridItemChangedEvent.cs
- DescendentsWalker.cs
- SqlProvider.cs
- XmlSignatureManifest.cs
- ForwardPositionQuery.cs
- WebPartAuthorizationEventArgs.cs
- UserControlAutomationPeer.cs
- HScrollProperties.cs
- SessionStateModule.cs
- ToolStripDropDownClosingEventArgs.cs
- ToolStripDropDownClosedEventArgs.cs
- AffineTransform3D.cs