Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Framework / System / Windows / Controls / PasswordBox.cs / 1305600 / PasswordBox.cs
//---------------------------------------------------------------------------- // // File: PasswordBox.cs // // Copyright (C) Microsoft Corporation. All rights reserved. // // Description: The stock password control. // //--------------------------------------------------------------------------- using System.Diagnostics; using System.Collections; using System.ComponentModel; using System.Globalization; using System.Security; using System.Text; using System.Windows.Media; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Automation; using System.Windows.Automation.Peers; using System.Windows.Input; using System.Windows.Navigation; using System.Windows.Shapes; using System.Windows.Threading; using MS.Internal; using MS.Internal.KnownBoxes; using System.Security.Permissions; using System.Windows.Controls.Primitives; #pragma warning disable 1634, 1691 // suppressing PreSharp warnings namespace System.Windows.Controls { ////// The stock password control. /// #if OLD_AUTOMATION [Automation(AccessibilityControlType = "Edit")] #endif [TemplatePart(Name = "PART_ContentHost", Type = typeof(FrameworkElement))] public sealed class PasswordBox : Control, ITextBoxViewHost #if OLD_AUTOMATION , IAutomationPatternProvider, IAutomationPropertyProvider #endif { //----------------------------------------------------- // // Constructors // //----------------------------------------------------- #region Constructors ////// Static constructor for PasswordBox. /// static PasswordBox() { DefaultStyleKeyProperty.OverrideMetadata(typeof(PasswordBox), new FrameworkPropertyMetadata(typeof(PasswordBox))); _dType = DependencyObjectType.FromSystemTypeInternal(typeof(PasswordBox)); // PasswordBox properties // ------------------ PasswordCharProperty.OverrideMetadata(typeof(PasswordBox), new FrameworkPropertyMetadata(new PropertyChangedCallback(OnPasswordCharChanged))); // Declaree listener for Padding property Control.PaddingProperty.OverrideMetadata(typeof(PasswordBox), new FrameworkPropertyMetadata(new PropertyChangedCallback(OnPaddingChanged))); // Prevent journaling NavigationService.NavigationServiceProperty.OverrideMetadata(typeof(PasswordBox), new FrameworkPropertyMetadata(new PropertyChangedCallback(OnParentNavigationServiceChanged))); InputMethod.IsInputMethodEnabledProperty.OverrideMetadata(typeof(PasswordBox), new FrameworkPropertyMetadata( BooleanBoxes.FalseBox, FrameworkPropertyMetadataOptions.Inherits, null, // new CoerceValueCallback(ForceToFalse))); // VSM IsEnabledProperty.OverrideMetadata(typeof(PasswordBox), new UIPropertyMetadata(new PropertyChangedCallback(OnVisualStatePropertyChanged))); IsMouseOverPropertyKey.OverrideMetadata(typeof(PasswordBox), new UIPropertyMetadata(new PropertyChangedCallback(OnVisualStatePropertyChanged))); TextBoxBase.SelectionBrushProperty.OverrideMetadata(typeof(PasswordBox), new FrameworkPropertyMetadata(new PropertyChangedCallback(UpdateCaretElement))); TextBoxBase.SelectionOpacityProperty.OverrideMetadata(typeof(PasswordBox), new FrameworkPropertyMetadata(new PropertyChangedCallback(UpdateCaretElement))); TextBoxBase.CaretBrushProperty.OverrideMetadata(typeof(PasswordBox), new FrameworkPropertyMetadata(new PropertyChangedCallback(UpdateCaretElement))); } ////// Constructor. /// public PasswordBox() : base() { Initialize(); } #endregion Constructors //------------------------------------------------------ // // Public Methods // //----------------------------------------------------- #region Public Methods ////// Replaces the current selection in the passwordbox with the contents /// of the Clipboard /// public void Paste() { RoutedCommand command = ApplicationCommands.Paste; command.Execute(null, this); } ////// Select all text in the PasswordBox /// public void SelectAll() { Selection.Select(TextContainer.Start, TextContainer.End); } ////// Clear all the content in the PasswordBox control. /// public void Clear() { this.Password = String.Empty; } #endregion Public Methods //------------------------------------------------------ // // Public Properties // //------------------------------------------------------ #region Public Properties ////// Contents of the PasswordBox. /// ////// Use the SecurePassword property in place of this one when possible. /// Doing so reduces the risk of revealing content that should be kept secret. /// ////// Critical - The getter elevates to unmanaged code and has unsafe code block. /// The setter calls SetSecurePassword. /// /// PublicOK: Does not pass unsafe data to native code. /// Does not pass 2nd party SecureString to SetSecurePassword. /// /// [DefaultValue("")] [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public string Password { [SecurityCritical] get { string password; using (SecureString securePassword = this.SecurePassword) { IntPtr ptr = System.Runtime.InteropServices.Marshal.SecureStringToBSTR(securePassword); try { unsafe { password = new string((char*)ptr); } } finally { System.Runtime.InteropServices.Marshal.ZeroFreeBSTR(ptr); } } return password; } [SecurityCritical] set { if (value == null) { value = String.Empty; } using (SecureString securePassword = new SecureString()) { #pragma warning suppress 6506 // value is set to String.Empty if it was null. for (int i = 0; i < value.Length; i++) { securePassword.AppendChar(value[i]); } SetSecurePassword(securePassword); } } } ////// Contents of the PasswordBox. /// ////// Reading the Password always returns a copy which may be safely /// Disposed. /// /// Setting the value always stores a copy of the supplied value. /// ////// Do not add public setter, see SetSecurePassword comments. /// [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public SecureString SecurePassword { get { return this.TextContainer.GetPasswordCopy(); } } ////// The DependencyID for the PasswordChar property. /// Default Value: '*' /// public static readonly DependencyProperty PasswordCharProperty = DependencyProperty.RegisterAttached( "PasswordChar", // Property name typeof(char), // Property type typeof(PasswordBox), // Property owner new FrameworkPropertyMetadata('*')); // Flags ////// Character to display instead of the actual password. /// public char PasswordChar { get { return (char) GetValue(PasswordCharProperty); } set { SetValue(PasswordCharProperty, value); } } ////// The limit number of characters that the PasswordBox or other editable controls can contain. /// if it is 0, means no-limitation. /// User can set this value for some simple single line PasswordBox to restrict the text number. /// By default it is 0. /// ////// When this property is set to zero, the maximum length of the text that can be entered /// in the control is limited only by available memory. You can use this property to restrict /// the length of text entered in the control for values such as postal codes and telephone numbers. /// You can also use this property to restrict the length of text entered when the data is to be entered /// in a database. /// You can limit the text entered into the control to the maximum length of the corresponding field in the database. /// Note: In code, you can set the value of the Text property to a value that is larger than /// the value specified by the MaxLength property. /// This property only affects text entered into the control at runtime. /// public static readonly DependencyProperty MaxLengthProperty = TextBox.MaxLengthProperty.AddOwner(typeof(PasswordBox)); ////// Maximum number of characters the PasswordBox can accept /// [DefaultValue((int)0)] public int MaxLength { get { return (int) GetValue(MaxLengthProperty); } set { SetValue(MaxLengthProperty, value); } } ////// public static readonly DependencyProperty SelectionBrushProperty = TextBoxBase.SelectionBrushProperty.AddOwner(typeof(PasswordBox)); ////// /// public Brush SelectionBrush { get { return (Brush)GetValue(SelectionBrushProperty); } set { SetValue(SelectionBrushProperty, value); } } ////// /// public static readonly DependencyProperty SelectionOpacityProperty = TextBoxBase.SelectionOpacityProperty.AddOwner(typeof(PasswordBox)); ////// /// public double SelectionOpacity { get { return (double)GetValue(SelectionOpacityProperty); } set { SetValue(SelectionOpacityProperty, value); } } ////// /// public static readonly DependencyProperty CaretBrushProperty = TextBoxBase.CaretBrushProperty.AddOwner(typeof(PasswordBox)); ////// /// public Brush CaretBrush { get { return (Brush)GetValue(CaretBrushProperty); } set { SetValue(CaretBrushProperty, value); } } #endregion Public Properties //----------------------------------------------------- // // Public Events // //------------------------------------------------------ #region Public Events ////// /// Event for "Text has changed" /// ////// Unlike most RoutedEvents on Controls, PasswordChangedEvent does not /// have a matching protected virtual OnPasswordChanged method -- /// because PasswordBox is sealed. /// public static readonly RoutedEvent PasswordChangedEvent = EventManager.RegisterRoutedEvent( "PasswordChanged", // Event name RoutingStrategy.Bubble, // typeof(RoutedEventHandler), // typeof(PasswordBox)); // ////// Event fired from this text box when its inner content /// has been changed. /// ////// It is redirected from inner TextContainer.Changed event. /// public event RoutedEventHandler PasswordChanged { add { AddHandler(PasswordChangedEvent, value); } remove { RemoveHandler(PasswordChangedEvent, value); } } #endregion Public Events //----------------------------------------------------- // // Protected Methods // //----------------------------------------------------- #region Protected Methods internal override void ChangeVisualState(bool useTransitions) { if (!IsEnabled) { VisualStates.GoToState(this, useTransitions, VisualStates.StateDisabled, VisualStates.StateNormal); } else if (IsMouseOver) { VisualStates.GoToState(this, useTransitions, VisualStates.StateMouseOver, VisualStates.StateNormal); } else { VisualStateManager.GoToState(this, VisualStates.StateNormal, useTransitions); } if (IsKeyboardFocused) { VisualStates.GoToState(this, useTransitions, VisualStates.StateFocused, VisualStates.StateUnfocused); } else { VisualStateManager.GoToState(this, VisualStates.StateUnfocused, useTransitions); } base.ChangeVisualState(useTransitions); } ////// Creates AutomationPeer ( protected override AutomationPeer OnCreateAutomationPeer() { return new PasswordBoxAutomationPeer(this); } ///) /// /// Called when the Template's tree has been generated /// public override void OnApplyTemplate() { base.OnApplyTemplate(); AttachToVisualTree(); } ////// Template has changed /// /// /// /// /// protected override void OnTemplateChanged(ControlTemplate oldTemplate, ControlTemplate newTemplate) { base.OnTemplateChanged(oldTemplate, newTemplate); if (oldTemplate!=null && newTemplate!= null && oldTemplate.VisualTree != newTemplate.VisualTree) { DetachFromVisualTree(); } } /// ////// protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e) { // always call base.OnPropertyChanged, otherwise Property Engine will not work. base.OnPropertyChanged(e); if (this.RenderScope != null) { FrameworkPropertyMetadata fmetadata = e.Property.GetMetadata(typeof(PasswordBox)) as FrameworkPropertyMetadata; if (fmetadata != null) { if (e.IsAValueChange || e.IsASubPropertyChange) { if (fmetadata.AffectsMeasure || fmetadata.AffectsArrange || fmetadata.AffectsParentMeasure || fmetadata.AffectsParentArrange || e.Property == Control.HorizontalContentAlignmentProperty || e.Property == Control.VerticalContentAlignmentProperty) { ((TextBoxView)this.RenderScope).Remeasure(); } else if (fmetadata.AffectsRender && (e.IsAValueChange || !fmetadata.SubPropertiesDoNotAffectRender)) { ((TextBoxView)this.RenderScope).Rerender(); } } } } } /// /// Virtual method reporting a key was pressed /// protected override void OnKeyDown(KeyEventArgs e) { base.OnKeyDown(e); if (e.Handled) { return; } _textEditor.OnKeyDown(e); } ////// Virtual method reporting a key was released /// protected override void OnKeyUp(KeyEventArgs e) { base.OnKeyUp(e); if (e.Handled) { return; } _textEditor.OnKeyUp(e); } ////// Virtual method reporting text composition /// protected override void OnTextInput(TextCompositionEventArgs e) { base.OnTextInput(e); if (e.Handled) { return; } _textEditor.OnTextInput(e); } ////// Virtual method reporting the mouse button was pressed /// protected override void OnMouseDown(MouseButtonEventArgs e) { base.OnMouseDown(e); if (e.Handled) { return; } _textEditor.OnMouseDown(e); } ////// Virtual method reporting a mouse move /// protected override void OnMouseMove(MouseEventArgs e) { base.OnMouseMove(e); if (e.Handled) { return; } _textEditor.OnMouseMove(e); } ////// Virtual method reporting the mouse button was released /// protected override void OnMouseUp(MouseButtonEventArgs e) { base.OnMouseUp(e); if (e.Handled) { return; } _textEditor.OnMouseUp(e); } ////// Virtual method reporting the cursor to display was requested /// protected override void OnQueryCursor(QueryCursorEventArgs e) { base.OnQueryCursor(e); if (e.Handled) { return; } _textEditor.OnQueryCursor(e); } ////// Virtual method reporting the query continue drag is going to happen /// protected override void OnQueryContinueDrag(QueryContinueDragEventArgs e) { base.OnQueryContinueDrag(e); if (e.Handled) { return; } _textEditor.OnQueryContinueDrag(e); } ////// Virtual method reporting the give feedback is going to happen /// protected override void OnGiveFeedback(GiveFeedbackEventArgs e) { base.OnGiveFeedback(e); if (e.Handled) { return; } _textEditor.OnGiveFeedback(e); } ////// Virtual method reporting the drag enter is going to happen /// protected override void OnDragEnter(DragEventArgs e) { base.OnDragEnter(e); if (e.Handled) { return; } _textEditor.OnDragEnter(e); } ////// Virtual method reporting the drag over is going to happen /// protected override void OnDragOver(DragEventArgs e) { base.OnDragOver(e); if (e.Handled) { return; } _textEditor.OnDragOver(e); } ////// Virtual method reporting the drag leave is going to happen /// protected override void OnDragLeave(DragEventArgs e) { base.OnDragLeave(e); if (e.Handled) { return; } _textEditor.OnDragLeave(e); } ////// Virtual method reporting the drag enter is going to happen /// protected override void OnDrop(DragEventArgs e) { base.OnDrop(e); if (e.Handled) { return; } _textEditor.OnDrop(e); } ////// Called when ContextMenuOpening is raised on this element. /// /// Event arguments protected override void OnContextMenuOpening(ContextMenuEventArgs e) { base.OnContextMenuOpening(e); if (e.Handled) { return; } _textEditor.OnContextMenuOpening(e); } ////// Virtual method reporting that the keyboard is focused on this element /// protected override void OnGotKeyboardFocus(KeyboardFocusChangedEventArgs e) { base.OnGotKeyboardFocus(e); if (e.Handled) { return; } _textEditor.OnGotKeyboardFocus(e); } ////// Virtual method reporting that the keyboard is no longer focusekeyboard is no longer focuseed /// protected override void OnLostKeyboardFocus(KeyboardFocusChangedEventArgs e) { base.OnLostKeyboardFocus(e); if (e.Handled) { return; } _textEditor.OnLostKeyboardFocus(e); } ////// This method is invoked when the IsFocused property changes to false /// /// RoutedEventArgs protected override void OnLostFocus(RoutedEventArgs e) { base.OnLostFocus(e); if (e.Handled) { return; } _textEditor.OnLostFocus(e); } #endregion Protected Methods //----------------------------------------------------- // // Internal Properties // //------------------------------------------------------ #region Internal Properties // A TextContainer covering the PasswordBox's inner content. internal PasswordTextContainer TextContainer { get { return _textContainer; } } ////// readonly access to internal content control /// internal FrameworkElement RenderScope { get { return _renderScope; } } internal ScrollViewer ScrollViewer { get { if (_scrollViewer == null) { if (_textEditor != null) { _scrollViewer = _textEditor._Scroller as ScrollViewer; } } return _scrollViewer; } } // ITextContainer holding the Control content. ITextContainer ITextBoxViewHost.TextContainer { get { return this.TextContainer; } } // Set true when typography property values are all default values. bool ITextBoxViewHost.IsTypographyDefaultValue { get { return true; } } #endregion Internal Properties //----------------------------------------------------- // // Private Methods // //------------------------------------------------------ #region Private Methods // Worker for the ctors, initializes a new PasswordBox instance. private void Initialize() { // Register static editing command handlers. // This only has an effect that first time we make the call. // We don't use the static ctor because there are cases // where another control will want to alias our properties // but doesn't need this overhead. TextEditor.RegisterCommandHandlers(typeof(PasswordBox), /*acceptsRichContent:*/false, /*readOnly*/false, /*registerEventListeners*/false); // Create TextContainer InitializeTextContainer(new PasswordTextContainer(this)); // PasswordBox only accepts plain text, so change TextEditor's default to that. _textEditor.AcceptsRichContent = false; // PasswordBox does not accetps tabs. _textEditor.AcceptsTab = false; } // Attaches this control to a new TextContainer. private void InitializeTextContainer(PasswordTextContainer textContainer) { Invariant.Assert(textContainer != null); // Uninitialize previous TextEditor if (_textContainer != null) { Invariant.Assert(_textEditor != null); Invariant.Assert(_textEditor.TextContainer == _textContainer); // Detach existing editor from VisualTree DetachFromVisualTree(); // Discard TextEditor - must release text container _textEditor.OnDetach(); } // Save text container _textContainer = textContainer; // ((ITextContainer)_textContainer).Changed += new TextContainerChangedEventHandler(OnTextContainerChanged); // Create a text editor, initialize undo manager for it, and link it to text container _textEditor = new TextEditor(_textContainer, this, true); } // Disable IME input unconditionally. We really can't support // IMEs in this control, because PasswordTextContainer doesn't // round-trip content, which breaks the cicero contract. // Additionally, from a UI standpoint, we don't want to break // user expectations by allowing IME input. IMEs do cool things // like learn from user corrections, so the same keystroke sequence // might produce different text over time. private static object ForceToFalse(DependencyObject d, object value) { return BooleanBoxes.FalseBox; } ////// Callback for changes to the PasswordChar property. /// private static void OnPasswordCharChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { PasswordBox passwordBox = (PasswordBox)d; // Force a layout refresh to display the new char. if (passwordBox._renderScope != null) { passwordBox._renderScope.InvalidateMeasure(); } } ////// Handler for text array change notifications. /// /// /// sender /// /// /// event args /// private void OnTextContainerChanged(object sender, TextContainerChangedEventArgs e) { // If only properties on the text changed, don't fire a content change event. // This can happen even in a plain text TextBox if we switch logical trees. if (!e.HasContentAddedOrRemoved) { return; } RaiseEvent(new RoutedEventArgs(PasswordChangedEvent)); } ////// Walk the visual tree until we find a Text control with IsPasswordBoxContent == true /// and a ScrollViewer /// private void SetRenderScopeToContentHost(TextBoxView renderScope) { // Clear the content host from previous render scope (if any) ClearContentHost(); // Find ContentHostTemplateName in the style _passwordBoxContentHost = GetTemplateChild(ContentHostTemplateName) as FrameworkElement; // Note that we allow ContentHostTemplateName to be optional. // This simplifies toolability of our control styling. // When the ContentHostTemplateName is not found or incorrect // PasswordBox goes into disabled state, but does not throw. // Add renderScope as a child of ContentHostTemplateName _renderScope = renderScope; if (_passwordBoxContentHost is ScrollViewer) { ScrollViewer scrollViewer = (ScrollViewer)_passwordBoxContentHost; if (scrollViewer.Content != null) { throw new NotSupportedException(SR.Get(SRID.TextBoxScrollViewerMarkedAsTextBoxContentMustHaveNoContent)); } else { scrollViewer.Content = _renderScope; } } else if (_passwordBoxContentHost is Decorator) { Decorator decorator = (Decorator)_passwordBoxContentHost; if (decorator.Child != null) { throw new NotSupportedException(SR.Get(SRID.TextBoxDecoratorMarkedAsTextBoxContentMustHaveNoContent)); } else { decorator.Child = _renderScope; // this may replace old render scope in case of upgrade scenario in TextBox } } else { // When we implement TextContainer setting via TextView interface // all text containing element will become allowed here. _renderScope = null; // Explicitly not throwing an exception here when content host = null // -- designers need us to support no content scenarios if (_passwordBoxContentHost != null) { _passwordBoxContentHost = null; // throw new NotSupportedException(SR.Get(SRID.PasswordBoxInvalidTextContainer)); } } // Attach render scope to TextEditor InitializeRenderScope(); FrameworkElement element = _renderScope; while (element != this && element != null) // checking both just to be safe { if (element is Border) { _border = (Border)element; } element = element.Parent as FrameworkElement; } } private void ClearContentHost() { // Detach render scope from TextEditor UninitializeRenderScope(); // Render scope has been created by us, // so we need to extract if from visual tree. if (_passwordBoxContentHost is ScrollViewer) { ((ScrollViewer)_passwordBoxContentHost).Content = null; } else if (_passwordBoxContentHost is Decorator) { ((Decorator)_passwordBoxContentHost).Child = null; } else { Invariant.Assert(_passwordBoxContentHost == null, "_passwordBoxContentHost must be null here"); } _passwordBoxContentHost = null; } // Initializes a new render scope. private void InitializeRenderScope() { if (_renderScope == null) { return; } // Attach the renderScope to TextEditor as its ITextView member. ITextView textview = TextEditor.GetTextView(_renderScope); _textEditor.TextView = textview; this.TextContainer.TextView = textview; if (this.ScrollViewer != null) { this.ScrollViewer.CanContentScroll = true; } } // Uninitializes a render scope and clears this control's reference. private void UninitializeRenderScope() { // Clear TextView property in TextEditor _textEditor.TextView = null; } // Resets the selection to the start of the content. // Called after non-TOM changes to the content, like // set_Text private void ResetSelection() { Select(0, 0); if (this.ScrollViewer != null) { this.ScrollViewer.ScrollToHome(); } } ////// Select the text in the given position and length. /// private void Select(int start, int length) { ITextPointer selectionStart; ITextPointer selectionEnd; // VerifyAccess(); if (start < 0) { throw new ArgumentOutOfRangeException("start", SR.Get(SRID.ParameterCannotBeNegative)); } if (length < 0) { throw new ArgumentOutOfRangeException("length", SR.Get(SRID.ParameterCannotBeNegative)); } // Identify new selection start position selectionStart = this.TextContainer.Start.CreatePointer(); while (start-- > 0 && selectionStart.MoveToNextInsertionPosition(LogicalDirection.Forward)) { } // Identify new selection end position selectionEnd = selectionStart.CreatePointer(); while (length-- > 0 && selectionEnd.MoveToNextInsertionPosition(LogicalDirection.Forward)) { } Selection.Select(selectionStart, selectionEnd); } ////// Callback for TextBox.Padding property setting /// /// /// TextBoxBase on which the property is changed /// /// event args private static void OnPaddingChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { PasswordBox passwordBox = (PasswordBox)d; if (passwordBox.ScrollViewer != null) { // translate this change into inner property set on ScrollViewer object padding = passwordBox.GetValue(Control.PaddingProperty); if (padding is Thickness) { passwordBox.ScrollViewer.Padding = (Thickness)padding; } else { passwordBox.ScrollViewer.ClearValue(Control.PaddingProperty); } } } // Set up listener for Navigating event private static void OnParentNavigationServiceChanged(DependencyObject o, DependencyPropertyChangedEventArgs e) { PasswordBox passwordBox = (PasswordBox)o; NavigationService navService = NavigationService.GetNavigationService(o); if (passwordBox._navigationService != null) { passwordBox._navigationService.Navigating -= new NavigatingCancelEventHandler(passwordBox.OnNavigating); } if (navService != null) { navService.Navigating += new NavigatingCancelEventHandler(passwordBox.OnNavigating); passwordBox._navigationService = navService; } else { passwordBox._navigationService = null; } } // Clear password on navigation to prevent journaling. private void OnNavigating(Object sender, NavigatingCancelEventArgs e) { this.Password = String.Empty; } ////// Detaches the editor from old visual tree and attaches it to a new one /// private void AttachToVisualTree() { DetachFromVisualTree(); // Walk the visual tree to find our Text element SetRenderScopeToContentHost(new TextBoxView(this)); // Attach scroll handler to the new scroll viewer // Note that this.ScrollViewer will walk the tree from current TextEditor's render scope up to its ui scope. if (this.ScrollViewer != null) { this.ScrollViewer.HorizontalScrollBarVisibility = ScrollBarVisibility.Hidden; this.ScrollViewer.VerticalScrollBarVisibility = ScrollBarVisibility.Disabled; this.ScrollViewer.Focusable = false; if (this.ScrollViewer.Background == null) { // prevent hit-testing through padding this.ScrollViewer.Background = Brushes.Transparent; } OnPaddingChanged(this, new DependencyPropertyChangedEventArgs()); } // Set border properties if (_border != null) { _border.Style = null; } } ////// Clear our layout-specific data, and detach our current renderScope from our text editor. /// private void DetachFromVisualTree() { if (_textEditor != null) { _textEditor.Selection.DetachFromVisualTree(); } // Invalidate our cached copy of scroll viewer. _scrollViewer = null; _border = null; ClearContentHost(); } ////// Sets the content of the control. /// ////// Critical - This method indirectly reveals value's SecureString content. /// /// This method must never be passed a publicly supplied SecureString as long as we expose /// a plain text get_Password property. /// /// 1. Attacker sets SecureString value it does not have permission to read. /// 2. Attacker reads Password property. /// --> attacker has ----ed open a SecureString without UnmanagedCode permission. /// [SecurityCritical] private void SetSecurePassword(SecureString value) { this.TextContainer.BeginChange(); try { this.TextContainer.SetPassword(value); this.ResetSelection(); } finally { this.TextContainer.EndChange(); } } ////// PropertyChanged callback for a property that affects the selection or caret rendering. /// private static void UpdateCaretElement(DependencyObject d, DependencyPropertyChangedEventArgs e) { PasswordBox passwordBox = (PasswordBox)d; if (passwordBox.Selection != null) { CaretElement caretElement = passwordBox.Selection.CaretElement; if (caretElement != null) { if (e.Property == CaretBrushProperty) { caretElement.UpdateCaretBrush(TextSelection.GetCaretBrush(passwordBox.Selection.TextEditor)); } caretElement.InvalidateVisual(); } } } #endregion Private methods //------------------------------------------------------ // // Private Properties // //----------------------------------------------------- #region Private Properties ////// Text Selection (readonly) /// private ITextSelection Selection { get { return _textEditor.Selection; } } #endregion Private Properties //------------------------------------------------------ // // Private Fields // //----------------------------------------------------- #region Private Fields // TextEditor working in this control instance private TextEditor _textEditor; // Backing store for the control's content. private PasswordTextContainer _textContainer; // Encapsulated control that renders our TextContainer. private TextBoxView _renderScope; // ScrollViewer private ScrollViewer _scrollViewer; // Border private Border _border; // An element marked as ContentHostTemplateName which we assign our _renderScope as a child. private FrameworkElement _passwordBoxContentHost; // Default size for the control. private const int _defaultWidth = 100; private const int _defaultHeight = 20; // Part name used in the style. The class TemplatePartAttribute should use the same name private const string ContentHostTemplateName = "PART_ContentHost"; #endregion Private Fields #region DTypeThemeStyleKey // Returns the DependencyObjectType for the registered ThemeStyleKey's default // value. Controls will override this method to return approriate types. internal override DependencyObjectType DTypeThemeStyleKey { get { return _dType; } } private static DependencyObjectType _dType; private NavigationService _navigationService; #endregion DTypeThemeStyleKey } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved. //---------------------------------------------------------------------------- // // File: PasswordBox.cs // // Copyright (C) Microsoft Corporation. All rights reserved. // // Description: The stock password control. // //--------------------------------------------------------------------------- using System.Diagnostics; using System.Collections; using System.ComponentModel; using System.Globalization; using System.Security; using System.Text; using System.Windows.Media; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Automation; using System.Windows.Automation.Peers; using System.Windows.Input; using System.Windows.Navigation; using System.Windows.Shapes; using System.Windows.Threading; using MS.Internal; using MS.Internal.KnownBoxes; using System.Security.Permissions; using System.Windows.Controls.Primitives; #pragma warning disable 1634, 1691 // suppressing PreSharp warnings namespace System.Windows.Controls { ////// The stock password control. /// #if OLD_AUTOMATION [Automation(AccessibilityControlType = "Edit")] #endif [TemplatePart(Name = "PART_ContentHost", Type = typeof(FrameworkElement))] public sealed class PasswordBox : Control, ITextBoxViewHost #if OLD_AUTOMATION , IAutomationPatternProvider, IAutomationPropertyProvider #endif { //----------------------------------------------------- // // Constructors // //----------------------------------------------------- #region Constructors ////// Static constructor for PasswordBox. /// static PasswordBox() { DefaultStyleKeyProperty.OverrideMetadata(typeof(PasswordBox), new FrameworkPropertyMetadata(typeof(PasswordBox))); _dType = DependencyObjectType.FromSystemTypeInternal(typeof(PasswordBox)); // PasswordBox properties // ------------------ PasswordCharProperty.OverrideMetadata(typeof(PasswordBox), new FrameworkPropertyMetadata(new PropertyChangedCallback(OnPasswordCharChanged))); // Declaree listener for Padding property Control.PaddingProperty.OverrideMetadata(typeof(PasswordBox), new FrameworkPropertyMetadata(new PropertyChangedCallback(OnPaddingChanged))); // Prevent journaling NavigationService.NavigationServiceProperty.OverrideMetadata(typeof(PasswordBox), new FrameworkPropertyMetadata(new PropertyChangedCallback(OnParentNavigationServiceChanged))); InputMethod.IsInputMethodEnabledProperty.OverrideMetadata(typeof(PasswordBox), new FrameworkPropertyMetadata( BooleanBoxes.FalseBox, FrameworkPropertyMetadataOptions.Inherits, null, // new CoerceValueCallback(ForceToFalse))); // VSM IsEnabledProperty.OverrideMetadata(typeof(PasswordBox), new UIPropertyMetadata(new PropertyChangedCallback(OnVisualStatePropertyChanged))); IsMouseOverPropertyKey.OverrideMetadata(typeof(PasswordBox), new UIPropertyMetadata(new PropertyChangedCallback(OnVisualStatePropertyChanged))); TextBoxBase.SelectionBrushProperty.OverrideMetadata(typeof(PasswordBox), new FrameworkPropertyMetadata(new PropertyChangedCallback(UpdateCaretElement))); TextBoxBase.SelectionOpacityProperty.OverrideMetadata(typeof(PasswordBox), new FrameworkPropertyMetadata(new PropertyChangedCallback(UpdateCaretElement))); TextBoxBase.CaretBrushProperty.OverrideMetadata(typeof(PasswordBox), new FrameworkPropertyMetadata(new PropertyChangedCallback(UpdateCaretElement))); } ////// Constructor. /// public PasswordBox() : base() { Initialize(); } #endregion Constructors //------------------------------------------------------ // // Public Methods // //----------------------------------------------------- #region Public Methods ////// Replaces the current selection in the passwordbox with the contents /// of the Clipboard /// public void Paste() { RoutedCommand command = ApplicationCommands.Paste; command.Execute(null, this); } ////// Select all text in the PasswordBox /// public void SelectAll() { Selection.Select(TextContainer.Start, TextContainer.End); } ////// Clear all the content in the PasswordBox control. /// public void Clear() { this.Password = String.Empty; } #endregion Public Methods //------------------------------------------------------ // // Public Properties // //------------------------------------------------------ #region Public Properties ////// Contents of the PasswordBox. /// ////// Use the SecurePassword property in place of this one when possible. /// Doing so reduces the risk of revealing content that should be kept secret. /// ////// Critical - The getter elevates to unmanaged code and has unsafe code block. /// The setter calls SetSecurePassword. /// /// PublicOK: Does not pass unsafe data to native code. /// Does not pass 2nd party SecureString to SetSecurePassword. /// /// [DefaultValue("")] [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public string Password { [SecurityCritical] get { string password; using (SecureString securePassword = this.SecurePassword) { IntPtr ptr = System.Runtime.InteropServices.Marshal.SecureStringToBSTR(securePassword); try { unsafe { password = new string((char*)ptr); } } finally { System.Runtime.InteropServices.Marshal.ZeroFreeBSTR(ptr); } } return password; } [SecurityCritical] set { if (value == null) { value = String.Empty; } using (SecureString securePassword = new SecureString()) { #pragma warning suppress 6506 // value is set to String.Empty if it was null. for (int i = 0; i < value.Length; i++) { securePassword.AppendChar(value[i]); } SetSecurePassword(securePassword); } } } ////// Contents of the PasswordBox. /// ////// Reading the Password always returns a copy which may be safely /// Disposed. /// /// Setting the value always stores a copy of the supplied value. /// ////// Do not add public setter, see SetSecurePassword comments. /// [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public SecureString SecurePassword { get { return this.TextContainer.GetPasswordCopy(); } } ////// The DependencyID for the PasswordChar property. /// Default Value: '*' /// public static readonly DependencyProperty PasswordCharProperty = DependencyProperty.RegisterAttached( "PasswordChar", // Property name typeof(char), // Property type typeof(PasswordBox), // Property owner new FrameworkPropertyMetadata('*')); // Flags ////// Character to display instead of the actual password. /// public char PasswordChar { get { return (char) GetValue(PasswordCharProperty); } set { SetValue(PasswordCharProperty, value); } } ////// The limit number of characters that the PasswordBox or other editable controls can contain. /// if it is 0, means no-limitation. /// User can set this value for some simple single line PasswordBox to restrict the text number. /// By default it is 0. /// ////// When this property is set to zero, the maximum length of the text that can be entered /// in the control is limited only by available memory. You can use this property to restrict /// the length of text entered in the control for values such as postal codes and telephone numbers. /// You can also use this property to restrict the length of text entered when the data is to be entered /// in a database. /// You can limit the text entered into the control to the maximum length of the corresponding field in the database. /// Note: In code, you can set the value of the Text property to a value that is larger than /// the value specified by the MaxLength property. /// This property only affects text entered into the control at runtime. /// public static readonly DependencyProperty MaxLengthProperty = TextBox.MaxLengthProperty.AddOwner(typeof(PasswordBox)); ////// Maximum number of characters the PasswordBox can accept /// [DefaultValue((int)0)] public int MaxLength { get { return (int) GetValue(MaxLengthProperty); } set { SetValue(MaxLengthProperty, value); } } ////// public static readonly DependencyProperty SelectionBrushProperty = TextBoxBase.SelectionBrushProperty.AddOwner(typeof(PasswordBox)); ////// /// public Brush SelectionBrush { get { return (Brush)GetValue(SelectionBrushProperty); } set { SetValue(SelectionBrushProperty, value); } } ////// /// public static readonly DependencyProperty SelectionOpacityProperty = TextBoxBase.SelectionOpacityProperty.AddOwner(typeof(PasswordBox)); ////// /// public double SelectionOpacity { get { return (double)GetValue(SelectionOpacityProperty); } set { SetValue(SelectionOpacityProperty, value); } } ////// /// public static readonly DependencyProperty CaretBrushProperty = TextBoxBase.CaretBrushProperty.AddOwner(typeof(PasswordBox)); ////// /// public Brush CaretBrush { get { return (Brush)GetValue(CaretBrushProperty); } set { SetValue(CaretBrushProperty, value); } } #endregion Public Properties //----------------------------------------------------- // // Public Events // //------------------------------------------------------ #region Public Events ////// /// Event for "Text has changed" /// ////// Unlike most RoutedEvents on Controls, PasswordChangedEvent does not /// have a matching protected virtual OnPasswordChanged method -- /// because PasswordBox is sealed. /// public static readonly RoutedEvent PasswordChangedEvent = EventManager.RegisterRoutedEvent( "PasswordChanged", // Event name RoutingStrategy.Bubble, // typeof(RoutedEventHandler), // typeof(PasswordBox)); // ////// Event fired from this text box when its inner content /// has been changed. /// ////// It is redirected from inner TextContainer.Changed event. /// public event RoutedEventHandler PasswordChanged { add { AddHandler(PasswordChangedEvent, value); } remove { RemoveHandler(PasswordChangedEvent, value); } } #endregion Public Events //----------------------------------------------------- // // Protected Methods // //----------------------------------------------------- #region Protected Methods internal override void ChangeVisualState(bool useTransitions) { if (!IsEnabled) { VisualStates.GoToState(this, useTransitions, VisualStates.StateDisabled, VisualStates.StateNormal); } else if (IsMouseOver) { VisualStates.GoToState(this, useTransitions, VisualStates.StateMouseOver, VisualStates.StateNormal); } else { VisualStateManager.GoToState(this, VisualStates.StateNormal, useTransitions); } if (IsKeyboardFocused) { VisualStates.GoToState(this, useTransitions, VisualStates.StateFocused, VisualStates.StateUnfocused); } else { VisualStateManager.GoToState(this, VisualStates.StateUnfocused, useTransitions); } base.ChangeVisualState(useTransitions); } ////// Creates AutomationPeer ( protected override AutomationPeer OnCreateAutomationPeer() { return new PasswordBoxAutomationPeer(this); } ///) /// /// Called when the Template's tree has been generated /// public override void OnApplyTemplate() { base.OnApplyTemplate(); AttachToVisualTree(); } ////// Template has changed /// /// /// /// /// protected override void OnTemplateChanged(ControlTemplate oldTemplate, ControlTemplate newTemplate) { base.OnTemplateChanged(oldTemplate, newTemplate); if (oldTemplate!=null && newTemplate!= null && oldTemplate.VisualTree != newTemplate.VisualTree) { DetachFromVisualTree(); } } /// ////// protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e) { // always call base.OnPropertyChanged, otherwise Property Engine will not work. base.OnPropertyChanged(e); if (this.RenderScope != null) { FrameworkPropertyMetadata fmetadata = e.Property.GetMetadata(typeof(PasswordBox)) as FrameworkPropertyMetadata; if (fmetadata != null) { if (e.IsAValueChange || e.IsASubPropertyChange) { if (fmetadata.AffectsMeasure || fmetadata.AffectsArrange || fmetadata.AffectsParentMeasure || fmetadata.AffectsParentArrange || e.Property == Control.HorizontalContentAlignmentProperty || e.Property == Control.VerticalContentAlignmentProperty) { ((TextBoxView)this.RenderScope).Remeasure(); } else if (fmetadata.AffectsRender && (e.IsAValueChange || !fmetadata.SubPropertiesDoNotAffectRender)) { ((TextBoxView)this.RenderScope).Rerender(); } } } } } /// /// Virtual method reporting a key was pressed /// protected override void OnKeyDown(KeyEventArgs e) { base.OnKeyDown(e); if (e.Handled) { return; } _textEditor.OnKeyDown(e); } ////// Virtual method reporting a key was released /// protected override void OnKeyUp(KeyEventArgs e) { base.OnKeyUp(e); if (e.Handled) { return; } _textEditor.OnKeyUp(e); } ////// Virtual method reporting text composition /// protected override void OnTextInput(TextCompositionEventArgs e) { base.OnTextInput(e); if (e.Handled) { return; } _textEditor.OnTextInput(e); } ////// Virtual method reporting the mouse button was pressed /// protected override void OnMouseDown(MouseButtonEventArgs e) { base.OnMouseDown(e); if (e.Handled) { return; } _textEditor.OnMouseDown(e); } ////// Virtual method reporting a mouse move /// protected override void OnMouseMove(MouseEventArgs e) { base.OnMouseMove(e); if (e.Handled) { return; } _textEditor.OnMouseMove(e); } ////// Virtual method reporting the mouse button was released /// protected override void OnMouseUp(MouseButtonEventArgs e) { base.OnMouseUp(e); if (e.Handled) { return; } _textEditor.OnMouseUp(e); } ////// Virtual method reporting the cursor to display was requested /// protected override void OnQueryCursor(QueryCursorEventArgs e) { base.OnQueryCursor(e); if (e.Handled) { return; } _textEditor.OnQueryCursor(e); } ////// Virtual method reporting the query continue drag is going to happen /// protected override void OnQueryContinueDrag(QueryContinueDragEventArgs e) { base.OnQueryContinueDrag(e); if (e.Handled) { return; } _textEditor.OnQueryContinueDrag(e); } ////// Virtual method reporting the give feedback is going to happen /// protected override void OnGiveFeedback(GiveFeedbackEventArgs e) { base.OnGiveFeedback(e); if (e.Handled) { return; } _textEditor.OnGiveFeedback(e); } ////// Virtual method reporting the drag enter is going to happen /// protected override void OnDragEnter(DragEventArgs e) { base.OnDragEnter(e); if (e.Handled) { return; } _textEditor.OnDragEnter(e); } ////// Virtual method reporting the drag over is going to happen /// protected override void OnDragOver(DragEventArgs e) { base.OnDragOver(e); if (e.Handled) { return; } _textEditor.OnDragOver(e); } ////// Virtual method reporting the drag leave is going to happen /// protected override void OnDragLeave(DragEventArgs e) { base.OnDragLeave(e); if (e.Handled) { return; } _textEditor.OnDragLeave(e); } ////// Virtual method reporting the drag enter is going to happen /// protected override void OnDrop(DragEventArgs e) { base.OnDrop(e); if (e.Handled) { return; } _textEditor.OnDrop(e); } ////// Called when ContextMenuOpening is raised on this element. /// /// Event arguments protected override void OnContextMenuOpening(ContextMenuEventArgs e) { base.OnContextMenuOpening(e); if (e.Handled) { return; } _textEditor.OnContextMenuOpening(e); } ////// Virtual method reporting that the keyboard is focused on this element /// protected override void OnGotKeyboardFocus(KeyboardFocusChangedEventArgs e) { base.OnGotKeyboardFocus(e); if (e.Handled) { return; } _textEditor.OnGotKeyboardFocus(e); } ////// Virtual method reporting that the keyboard is no longer focusekeyboard is no longer focuseed /// protected override void OnLostKeyboardFocus(KeyboardFocusChangedEventArgs e) { base.OnLostKeyboardFocus(e); if (e.Handled) { return; } _textEditor.OnLostKeyboardFocus(e); } ////// This method is invoked when the IsFocused property changes to false /// /// RoutedEventArgs protected override void OnLostFocus(RoutedEventArgs e) { base.OnLostFocus(e); if (e.Handled) { return; } _textEditor.OnLostFocus(e); } #endregion Protected Methods //----------------------------------------------------- // // Internal Properties // //------------------------------------------------------ #region Internal Properties // A TextContainer covering the PasswordBox's inner content. internal PasswordTextContainer TextContainer { get { return _textContainer; } } ////// readonly access to internal content control /// internal FrameworkElement RenderScope { get { return _renderScope; } } internal ScrollViewer ScrollViewer { get { if (_scrollViewer == null) { if (_textEditor != null) { _scrollViewer = _textEditor._Scroller as ScrollViewer; } } return _scrollViewer; } } // ITextContainer holding the Control content. ITextContainer ITextBoxViewHost.TextContainer { get { return this.TextContainer; } } // Set true when typography property values are all default values. bool ITextBoxViewHost.IsTypographyDefaultValue { get { return true; } } #endregion Internal Properties //----------------------------------------------------- // // Private Methods // //------------------------------------------------------ #region Private Methods // Worker for the ctors, initializes a new PasswordBox instance. private void Initialize() { // Register static editing command handlers. // This only has an effect that first time we make the call. // We don't use the static ctor because there are cases // where another control will want to alias our properties // but doesn't need this overhead. TextEditor.RegisterCommandHandlers(typeof(PasswordBox), /*acceptsRichContent:*/false, /*readOnly*/false, /*registerEventListeners*/false); // Create TextContainer InitializeTextContainer(new PasswordTextContainer(this)); // PasswordBox only accepts plain text, so change TextEditor's default to that. _textEditor.AcceptsRichContent = false; // PasswordBox does not accetps tabs. _textEditor.AcceptsTab = false; } // Attaches this control to a new TextContainer. private void InitializeTextContainer(PasswordTextContainer textContainer) { Invariant.Assert(textContainer != null); // Uninitialize previous TextEditor if (_textContainer != null) { Invariant.Assert(_textEditor != null); Invariant.Assert(_textEditor.TextContainer == _textContainer); // Detach existing editor from VisualTree DetachFromVisualTree(); // Discard TextEditor - must release text container _textEditor.OnDetach(); } // Save text container _textContainer = textContainer; // ((ITextContainer)_textContainer).Changed += new TextContainerChangedEventHandler(OnTextContainerChanged); // Create a text editor, initialize undo manager for it, and link it to text container _textEditor = new TextEditor(_textContainer, this, true); } // Disable IME input unconditionally. We really can't support // IMEs in this control, because PasswordTextContainer doesn't // round-trip content, which breaks the cicero contract. // Additionally, from a UI standpoint, we don't want to break // user expectations by allowing IME input. IMEs do cool things // like learn from user corrections, so the same keystroke sequence // might produce different text over time. private static object ForceToFalse(DependencyObject d, object value) { return BooleanBoxes.FalseBox; } ////// Callback for changes to the PasswordChar property. /// private static void OnPasswordCharChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { PasswordBox passwordBox = (PasswordBox)d; // Force a layout refresh to display the new char. if (passwordBox._renderScope != null) { passwordBox._renderScope.InvalidateMeasure(); } } ////// Handler for text array change notifications. /// /// /// sender /// /// /// event args /// private void OnTextContainerChanged(object sender, TextContainerChangedEventArgs e) { // If only properties on the text changed, don't fire a content change event. // This can happen even in a plain text TextBox if we switch logical trees. if (!e.HasContentAddedOrRemoved) { return; } RaiseEvent(new RoutedEventArgs(PasswordChangedEvent)); } ////// Walk the visual tree until we find a Text control with IsPasswordBoxContent == true /// and a ScrollViewer /// private void SetRenderScopeToContentHost(TextBoxView renderScope) { // Clear the content host from previous render scope (if any) ClearContentHost(); // Find ContentHostTemplateName in the style _passwordBoxContentHost = GetTemplateChild(ContentHostTemplateName) as FrameworkElement; // Note that we allow ContentHostTemplateName to be optional. // This simplifies toolability of our control styling. // When the ContentHostTemplateName is not found or incorrect // PasswordBox goes into disabled state, but does not throw. // Add renderScope as a child of ContentHostTemplateName _renderScope = renderScope; if (_passwordBoxContentHost is ScrollViewer) { ScrollViewer scrollViewer = (ScrollViewer)_passwordBoxContentHost; if (scrollViewer.Content != null) { throw new NotSupportedException(SR.Get(SRID.TextBoxScrollViewerMarkedAsTextBoxContentMustHaveNoContent)); } else { scrollViewer.Content = _renderScope; } } else if (_passwordBoxContentHost is Decorator) { Decorator decorator = (Decorator)_passwordBoxContentHost; if (decorator.Child != null) { throw new NotSupportedException(SR.Get(SRID.TextBoxDecoratorMarkedAsTextBoxContentMustHaveNoContent)); } else { decorator.Child = _renderScope; // this may replace old render scope in case of upgrade scenario in TextBox } } else { // When we implement TextContainer setting via TextView interface // all text containing element will become allowed here. _renderScope = null; // Explicitly not throwing an exception here when content host = null // -- designers need us to support no content scenarios if (_passwordBoxContentHost != null) { _passwordBoxContentHost = null; // throw new NotSupportedException(SR.Get(SRID.PasswordBoxInvalidTextContainer)); } } // Attach render scope to TextEditor InitializeRenderScope(); FrameworkElement element = _renderScope; while (element != this && element != null) // checking both just to be safe { if (element is Border) { _border = (Border)element; } element = element.Parent as FrameworkElement; } } private void ClearContentHost() { // Detach render scope from TextEditor UninitializeRenderScope(); // Render scope has been created by us, // so we need to extract if from visual tree. if (_passwordBoxContentHost is ScrollViewer) { ((ScrollViewer)_passwordBoxContentHost).Content = null; } else if (_passwordBoxContentHost is Decorator) { ((Decorator)_passwordBoxContentHost).Child = null; } else { Invariant.Assert(_passwordBoxContentHost == null, "_passwordBoxContentHost must be null here"); } _passwordBoxContentHost = null; } // Initializes a new render scope. private void InitializeRenderScope() { if (_renderScope == null) { return; } // Attach the renderScope to TextEditor as its ITextView member. ITextView textview = TextEditor.GetTextView(_renderScope); _textEditor.TextView = textview; this.TextContainer.TextView = textview; if (this.ScrollViewer != null) { this.ScrollViewer.CanContentScroll = true; } } // Uninitializes a render scope and clears this control's reference. private void UninitializeRenderScope() { // Clear TextView property in TextEditor _textEditor.TextView = null; } // Resets the selection to the start of the content. // Called after non-TOM changes to the content, like // set_Text private void ResetSelection() { Select(0, 0); if (this.ScrollViewer != null) { this.ScrollViewer.ScrollToHome(); } } ////// Select the text in the given position and length. /// private void Select(int start, int length) { ITextPointer selectionStart; ITextPointer selectionEnd; // VerifyAccess(); if (start < 0) { throw new ArgumentOutOfRangeException("start", SR.Get(SRID.ParameterCannotBeNegative)); } if (length < 0) { throw new ArgumentOutOfRangeException("length", SR.Get(SRID.ParameterCannotBeNegative)); } // Identify new selection start position selectionStart = this.TextContainer.Start.CreatePointer(); while (start-- > 0 && selectionStart.MoveToNextInsertionPosition(LogicalDirection.Forward)) { } // Identify new selection end position selectionEnd = selectionStart.CreatePointer(); while (length-- > 0 && selectionEnd.MoveToNextInsertionPosition(LogicalDirection.Forward)) { } Selection.Select(selectionStart, selectionEnd); } ////// Callback for TextBox.Padding property setting /// /// /// TextBoxBase on which the property is changed /// /// event args private static void OnPaddingChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { PasswordBox passwordBox = (PasswordBox)d; if (passwordBox.ScrollViewer != null) { // translate this change into inner property set on ScrollViewer object padding = passwordBox.GetValue(Control.PaddingProperty); if (padding is Thickness) { passwordBox.ScrollViewer.Padding = (Thickness)padding; } else { passwordBox.ScrollViewer.ClearValue(Control.PaddingProperty); } } } // Set up listener for Navigating event private static void OnParentNavigationServiceChanged(DependencyObject o, DependencyPropertyChangedEventArgs e) { PasswordBox passwordBox = (PasswordBox)o; NavigationService navService = NavigationService.GetNavigationService(o); if (passwordBox._navigationService != null) { passwordBox._navigationService.Navigating -= new NavigatingCancelEventHandler(passwordBox.OnNavigating); } if (navService != null) { navService.Navigating += new NavigatingCancelEventHandler(passwordBox.OnNavigating); passwordBox._navigationService = navService; } else { passwordBox._navigationService = null; } } // Clear password on navigation to prevent journaling. private void OnNavigating(Object sender, NavigatingCancelEventArgs e) { this.Password = String.Empty; } ////// Detaches the editor from old visual tree and attaches it to a new one /// private void AttachToVisualTree() { DetachFromVisualTree(); // Walk the visual tree to find our Text element SetRenderScopeToContentHost(new TextBoxView(this)); // Attach scroll handler to the new scroll viewer // Note that this.ScrollViewer will walk the tree from current TextEditor's render scope up to its ui scope. if (this.ScrollViewer != null) { this.ScrollViewer.HorizontalScrollBarVisibility = ScrollBarVisibility.Hidden; this.ScrollViewer.VerticalScrollBarVisibility = ScrollBarVisibility.Disabled; this.ScrollViewer.Focusable = false; if (this.ScrollViewer.Background == null) { // prevent hit-testing through padding this.ScrollViewer.Background = Brushes.Transparent; } OnPaddingChanged(this, new DependencyPropertyChangedEventArgs()); } // Set border properties if (_border != null) { _border.Style = null; } } ////// Clear our layout-specific data, and detach our current renderScope from our text editor. /// private void DetachFromVisualTree() { if (_textEditor != null) { _textEditor.Selection.DetachFromVisualTree(); } // Invalidate our cached copy of scroll viewer. _scrollViewer = null; _border = null; ClearContentHost(); } ////// Sets the content of the control. /// ////// Critical - This method indirectly reveals value's SecureString content. /// /// This method must never be passed a publicly supplied SecureString as long as we expose /// a plain text get_Password property. /// /// 1. Attacker sets SecureString value it does not have permission to read. /// 2. Attacker reads Password property. /// --> attacker has ----ed open a SecureString without UnmanagedCode permission. /// [SecurityCritical] private void SetSecurePassword(SecureString value) { this.TextContainer.BeginChange(); try { this.TextContainer.SetPassword(value); this.ResetSelection(); } finally { this.TextContainer.EndChange(); } } ////// PropertyChanged callback for a property that affects the selection or caret rendering. /// private static void UpdateCaretElement(DependencyObject d, DependencyPropertyChangedEventArgs e) { PasswordBox passwordBox = (PasswordBox)d; if (passwordBox.Selection != null) { CaretElement caretElement = passwordBox.Selection.CaretElement; if (caretElement != null) { if (e.Property == CaretBrushProperty) { caretElement.UpdateCaretBrush(TextSelection.GetCaretBrush(passwordBox.Selection.TextEditor)); } caretElement.InvalidateVisual(); } } } #endregion Private methods //------------------------------------------------------ // // Private Properties // //----------------------------------------------------- #region Private Properties ////// Text Selection (readonly) /// private ITextSelection Selection { get { return _textEditor.Selection; } } #endregion Private Properties //------------------------------------------------------ // // Private Fields // //----------------------------------------------------- #region Private Fields // TextEditor working in this control instance private TextEditor _textEditor; // Backing store for the control's content. private PasswordTextContainer _textContainer; // Encapsulated control that renders our TextContainer. private TextBoxView _renderScope; // ScrollViewer private ScrollViewer _scrollViewer; // Border private Border _border; // An element marked as ContentHostTemplateName which we assign our _renderScope as a child. private FrameworkElement _passwordBoxContentHost; // Default size for the control. private const int _defaultWidth = 100; private const int _defaultHeight = 20; // Part name used in the style. The class TemplatePartAttribute should use the same name private const string ContentHostTemplateName = "PART_ContentHost"; #endregion Private Fields #region DTypeThemeStyleKey // Returns the DependencyObjectType for the registered ThemeStyleKey's default // value. Controls will override this method to return approriate types. internal override DependencyObjectType DTypeThemeStyleKey { get { return _dType; } } private static DependencyObjectType _dType; private NavigationService _navigationService; #endregion DTypeThemeStyleKey } } // 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
- ScaleTransform.cs
- BasicHttpSecurity.cs
- HttpRuntime.cs
- HitTestWithGeometryDrawingContextWalker.cs
- SynchronizedDisposablePool.cs
- IOException.cs
- SQLSingle.cs
- XhtmlConformanceSection.cs
- MemberAccessException.cs
- FormViewInsertEventArgs.cs
- ServiceProviders.cs
- ProfileModule.cs
- _RequestCacheProtocol.cs
- ParameterExpression.cs
- AssertFilter.cs
- TextBox.cs
- AutomationProperty.cs
- Evidence.cs
- OleDbError.cs
- MaskDescriptor.cs
- NamespaceList.cs
- MeshGeometry3D.cs
- HwndAppCommandInputProvider.cs
- _AutoWebProxyScriptWrapper.cs
- DockPatternIdentifiers.cs
- __ConsoleStream.cs
- Label.cs
- Tile.cs
- ClientWindowsAuthenticationMembershipProvider.cs
- HtmlContainerControl.cs
- ExceptionUtil.cs
- CompilerLocalReference.cs
- DBDataPermission.cs
- DataPagerFieldCollection.cs
- coordinatorfactory.cs
- BindingNavigator.cs
- OleDbParameter.cs
- Attribute.cs
- TextDecoration.cs
- RoleGroupCollectionEditor.cs
- InProcStateClientManager.cs
- ComponentManagerBroker.cs
- BrowserDefinitionCollection.cs
- Vector3DAnimation.cs
- RadioButtonBaseAdapter.cs
- MouseEventArgs.cs
- ParameterDataSourceExpression.cs
- SchemaImporterExtension.cs
- WebBrowserDesigner.cs
- PopupControlService.cs
- SQLStringStorage.cs
- SessionPageStateSection.cs
- EditorPartChrome.cs
- PageRequestManager.cs
- FromRequest.cs
- IndentedTextWriter.cs
- WebPartPersonalization.cs
- PolicyStatement.cs
- WindowsScrollBar.cs
- Profiler.cs
- SiteMapProvider.cs
- SizeAnimationClockResource.cs
- UIAgentInitializationException.cs
- _Connection.cs
- SafeHandles.cs
- SqlConnectionHelper.cs
- LazyTextWriterCreator.cs
- SafeNativeMethods.cs
- WsdlInspector.cs
- ZipIOLocalFileBlock.cs
- OperationFormatter.cs
- ObjectSet.cs
- CustomServiceCredentials.cs
- HuffmanTree.cs
- MsmqAppDomainProtocolHandler.cs
- followingsibling.cs
- DependencyPropertyConverter.cs
- PropertyGeneratedEventArgs.cs
- CodeDelegateInvokeExpression.cs
- AsyncContentLoadedEventArgs.cs
- FrameworkObject.cs
- PageHandlerFactory.cs
- _DisconnectOverlappedAsyncResult.cs
- CodeDOMProvider.cs
- XamlParser.cs
- DuplicateWaitObjectException.cs
- TextEffectResolver.cs
- EvidenceTypeDescriptor.cs
- NullableBoolConverter.cs
- ContextStaticAttribute.cs
- AudioSignalProblemOccurredEventArgs.cs
- PreviewPageInfo.cs
- WizardPanel.cs
- MessageDescriptionCollection.cs
- ListItemCollection.cs
- TableRowCollection.cs
- Regex.cs
- TableLayoutCellPaintEventArgs.cs
- DocumentViewerHelper.cs
- CodeDomDesignerLoader.cs