| File: MS\Internal\Documents\Application\CommandEnforcer.cs | Web Access |
| Project: src\wpf\src\Microsoft.DotNet.Wpf\src\PresentationUI\PresentationUI.csproj (PresentationUI) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // Description: Manager for Enforcing RM Permissions on DocumentApplication-specific RoutedUICommands. using System; using System.Collections.Generic; using System.Runtime.InteropServices; using System.Windows.Input; namespace MS.Internal.Documents.Application { /// <summary> /// A PolicyBinding represents a binding between a Command and the RMPolicy required to /// Invoke said command. /// </summary> internal sealed class PolicyBinding { /// <summary> /// Constructor for a PolicyBinding. /// </summary> /// <param name="command">The Command to bind the permission to.</param> /// <param name="policy">The RMPolicy to be bound to the above Command.</param> public PolicyBinding(RoutedUICommand command, RightsManagementPolicy policy) { ArgumentNullException.ThrowIfNull(command); _command = command; _policy = policy; } /// <summary> /// The Command associated with this binding. /// </summary> public RoutedUICommand Command { get { return _command; } } /// <summary> /// The RMPolicy associated with this binding. /// </summary> public RightsManagementPolicy Policy { get { return _policy; } } private RoutedUICommand _command; private RightsManagementPolicy _policy; } /// <summary> /// The CommandEnforcer class provides a very simple central repository for RM enforced /// Commands used by Mongoose. /// </summary> internal sealed class CommandEnforcer { /// <summary> /// Constructor /// </summary> /// <param name="docViewer">The DocumentApplicationDocumentViewer parent.</param> internal CommandEnforcer(DocumentApplicationDocumentViewer docViewer) { //Create our bindings List. _bindings = new List<PolicyBinding>(_initialBindCount); _docViewer = docViewer; } /// <summary> /// Finalizer /// </summary> ~CommandEnforcer() { // Ensure that PrintScreen is re-enabled in native code DisablePrintScreen(false); } /// <summary> /// Adds a new binding to the Enforcer. /// NOTE: CommandEnforcer does not check for duplicate entries, so be warned /// that if you have duplicate entries, the newest duplicate will be the one whose /// enforcement is honored. /// </summary> /// <param name="bind">The binding to add</param> internal void AddBinding(PolicyBinding bind) { ArgumentNullException.ThrowIfNull(bind); _bindings.Add(bind); } /// <summary> /// Enforces the RMPolicy by walking through the PolicyBinding and setting the /// IsBlockedByRM property on the associated Commands as appropriate. /// </summary> /// <param name="policyToEnforce"></param> internal void Enforce() { Invariant.Assert( _docViewer != null, "CommandEnforcer has no reference to the parent DocumentApplicationDocumentViewer."); // Get the current policy from the parent DocumentApplicationDocumentViewer RightsManagementPolicy policyToEnforce = _docViewer.RightsManagementPolicy; // Walk through the list of bindings foreach (PolicyBinding binding in _bindings) { // If the incoming policy allows this action, and it completely masks our binding policy, // then we set the IsBlockedByRM property to false, as this Command is permitted. binding.Command.IsBlockedByRM = !((policyToEnforce & binding.Policy) == binding.Policy); } // Enforce PrintScreen // This will disable PrintScreen if neither AllowCopy or AllowPrint // permission is granted. bool disablePrintScreen = !(((policyToEnforce & RightsManagementPolicy.AllowCopy) == RightsManagementPolicy.AllowCopy) || ((policyToEnforce & RightsManagementPolicy.AllowPrint) == RightsManagementPolicy.AllowPrint)); DisablePrintScreen(disablePrintScreen); } /// <summary> /// Disable all PrintScreen related functions in the system. /// </summary> /// <param name="disable">True if PrintScreen should be disabled, false otherwise.</param> private void DisablePrintScreen(bool disable) { // To ensure that everytime PrintScreen is disabled it is also re-enabled we // only issue the system call if the value has changed. if (disable != _printScreenDisabled) { // Check if currently running in 32bit and that RM is available. if ((!_isRMMissing) && (IntPtr.Size == 4)) { // Initialize hresult to a valid return value. int hresult = UnsafeNativeMethods.FAIL; try { // Make call to RM API here to change the count. hresult = UnsafeNativeMethods.DRMRegisterContent(disable); } catch (System.DllNotFoundException) { // We could not find MSDRM.DLL to disable the print screen. // Just silently catch this exception and fail. // This is safe to catch, because it means that RM is not // installed on the machine so we don't need to worry about // disabling the print screen. _isRMMissing = true; } // Result should be S_OK for successful value assignment. Trace.SafeWrite( Trace.Presentation, "CommandEnforcer: DisablePrintScreen change to: {0} hresult: {1}", disable, hresult); } // Update property with new value _printScreenDisabled = disable; } } /// <summary> /// The list of bindings to enforce. /// </summary> private List<PolicyBinding> _bindings; private DocumentApplicationDocumentViewer _docViewer; private const int _initialBindCount = 10; //We allocate space for 10 bindings initially. /// <summary> /// _printScreenDisabled is used to track the current PrintScreen state. It begins with /// false since PrintScreen is initially enabled, and tracks changes from there. /// </summary> private bool _printScreenDisabled; // Trusted to be initialized to false /// <summary> /// _isRMMissing is used to track if a successful call has been made to native RM. /// This is used for performance, to limit the number of Exceptions being caught. /// </summary> private bool _isRMMissing; // Initially assumed that RM is installed and working. #region UnsafeNativeMethods (Private Class) /// <summary> /// This class is used to provide access to unmanaged code in order to disable /// the native PrintScreen support. /// </summary> private static class UnsafeNativeMethods { /// <summary> /// Called to toggle native PrintScreen support. This will increment/decrement /// a reference counter, so it must be reset after use (for stability). /// </summary> /// <param name="register">A bool value to determine if PrintScreen should be /// disabled. True means disabled, false re-enables.</param> /// <returns>S_OK on success, an error code otherwise.</returns> [DllImport("msdrm.dll", SetLastError = false, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)] public static extern int DRMRegisterContent(bool register); /// <summary> /// Non-success value. /// </summary> // This value can be anything other than S_OK internal const int FAIL = -1; } #endregion UnsafeNativeMethods } }