File: winforms\Managed\System\WinForms\AccessibleObject.cs
Project: ndp\fx\src\System.Windows.Forms.csproj (System.Windows.Forms)
//------------------------------------------------------------------------------
// <copyright file="AccessibleObject.cs" company="Microsoft">
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// </copyright>                                                                
//------------------------------------------------------------------------------
 
/*
 */
 
namespace System.Windows.Forms {
    using Accessibility;
    using System.Runtime.InteropServices;
    using System.Diagnostics;
    using System;
    using System.Collections;
    using System.Drawing;
    using System.Windows.Forms;
    using Microsoft.Win32;
    using System.ComponentModel;
    using System.Reflection;
    using System.Globalization;
    using System.Security;
    using System.Security.Permissions;
    using Automation;
    
    /// <include file='doc\AccessibleObject.uex' path='docs/doc[@for="AccessibleObject"]/*' />
    /// <devdoc>
    ///    <para>Provides an implementation for an object that can be inspected by an 
    ///       accessibility application.</para>    
    /// </devdoc>
    [ComVisible(true)]
    public class AccessibleObject : StandardOleMarshalObject,
                                    IReflect,
                                    IAccessible,
                                    UnsafeNativeMethods.IAccessibleEx,
                                    UnsafeNativeMethods.IServiceProvider,
                                    UnsafeNativeMethods.IRawElementProviderSimple,
                                    UnsafeNativeMethods.IRawElementProviderFragment,
                                    UnsafeNativeMethods.IRawElementProviderFragmentRoot,
                                    UnsafeNativeMethods.IInvokeProvider,
                                    UnsafeNativeMethods.IValueProvider,
                                    UnsafeNativeMethods.IRangeValueProvider,
                                    UnsafeNativeMethods.IExpandCollapseProvider,
                                    UnsafeNativeMethods.IToggleProvider,
                                    UnsafeNativeMethods.ITableProvider,
                                    UnsafeNativeMethods.ITableItemProvider,
                                    UnsafeNativeMethods.IGridProvider,
                                    UnsafeNativeMethods.IGridItemProvider,
                                    UnsafeNativeMethods.IEnumVariant,
                                    UnsafeNativeMethods.IOleWindow,
                                    UnsafeNativeMethods.ILegacyIAccessibleProvider,
                                    UnsafeNativeMethods.ISelectionProvider,
                                    UnsafeNativeMethods.ISelectionItemProvider,
                                    UnsafeNativeMethods.IRawElementProviderHwndOverride,
                                    UnsafeNativeMethods.IScrollItemProvider { 
 
        // Member variables
 
        /// <include file='doc\AccessibleObject.uex' path='docs/doc[@for="AccessibleObject.systemIAccessible"]/*' />
        /// <devdoc>
        /// <para>Specifies the <see langword='IAccessible '/>interface used by this <see cref='System.Windows.Forms.AccessibleObject'/>.</para>
        /// </devdoc>
        private IAccessible systemIAccessible = null;
 
        /// <include file='doc\AccessibleObject.uex' path='docs/doc[@for="AccessibleObject.systemIEnumVariant"]/*' />
        /// <devdoc>
        ///    <para>Specifies the 
        ///    <see langword='NativeMethods.IEnumVariant '/>used by this <see cref='System.Windows.Forms.AccessibleObject'/> .</para>
        /// </devdoc>
        private UnsafeNativeMethods.IEnumVariant systemIEnumVariant = null;
        private UnsafeNativeMethods.IEnumVariant enumVariant = null;
 
        // IOleWindow interface of the 'inner' system IAccessible object that we are wrapping
        private UnsafeNativeMethods.IOleWindow systemIOleWindow = null;
 
        private bool systemWrapper = false;     // Indicates this object is being used ONLY to wrap a system IAccessible
 
        private int accObjId = NativeMethods.OBJID_CLIENT;    // Indicates what kind of 'inner' system accessible object we are using
 
        // The support for the UIA Notification event begins in RS3.
        // Assume the UIA Notification event is available until we learn otherwise.
        // If we learn that the UIA Notification event is not available, 
        // controls should not attempt to raise it.
        private static bool notificationEventAvailable = true;
 
        internal const int RuntimeIDFirstItem = 0x2a;
 
        /// <include file='doc\AccessibleObject.uex' path='docs/doc[@for="AccessibleObject.AccessibleObject"]/*' />
        public AccessibleObject() {
        }
        
        // This constructor is used ONLY for wrapping system IAccessible objects
        //
        private AccessibleObject(IAccessible iAcc) {
            this.systemIAccessible = iAcc;            
            this.systemWrapper = true;
        }
        
        // Properties
 
        /// <include file='doc\AccessibleObject.uex' path='docs/doc[@for="AccessibleObject.Bounds"]/*' />
        /// <devdoc>
        ///    <para> Gets the bounds of the accessible object, in screen coordinates.</para>
        /// </devdoc>
        public virtual Rectangle Bounds {
            get {
                // Use the system provided bounds
                if (systemIAccessible != null) {
                    int left = 0;
                    int top = 0;
                    int width = 0;
                    int height = 0;
                    try {
                        systemIAccessible.accLocation(out left, out top, out width, out height, NativeMethods.CHILDID_SELF);
                        return new Rectangle(left, top, width, height);
                    }
                    catch (COMException e) {
                        if (e.ErrorCode != NativeMethods.DISP_E_MEMBERNOTFOUND) {
                            throw e;
                        }                        
                    }                    
                }
                return Rectangle.Empty;
            }
        }
        
        /// <include file='doc\AccessibleObject.uex' path='docs/doc[@for="AccessibleObject.DefaultAction"]/*' />
        /// <devdoc>
        ///    <para>Gets a description of the default action for an object.</para>
        /// </devdoc>
        public virtual string DefaultAction {
            get {
                if (systemIAccessible != null) {
                    try {
                        return systemIAccessible.get_accDefaultAction(NativeMethods.CHILDID_SELF);
                    }
                    catch (COMException e) {
                        // Not all objects provide a default action
                        //
                        if (e.ErrorCode != NativeMethods.DISP_E_MEMBERNOTFOUND) {
                            throw e;
                        }
                    }
                }
                return null;
            }
        }
        
        /// <include file='doc\AccessibleObject.uex' path='docs/doc[@for="AccessibleObject.Description"]/*' />
        /// <devdoc>
        ///    <para>Gets a description
        ///       of the object's visual appearance to the user.</para>
        /// </devdoc>
        public virtual string Description {
            get {
                if (systemIAccessible != null) {
                    try {
                        return systemIAccessible.get_accDescription(NativeMethods.CHILDID_SELF);
                    }
                    catch (COMException e) {
                        if (e.ErrorCode != NativeMethods.DISP_E_MEMBERNOTFOUND) {
                            throw e;
                        }
                    }
                }
                return null;
            }
        }
        
        private UnsafeNativeMethods.IEnumVariant EnumVariant {
            get {
                if (enumVariant == null) {
                    enumVariant = new EnumVariantObject(this);
                }
                return enumVariant;                
            }
        }
 
        /// <include file='doc\AccessibleObject.uex' path='docs/doc[@for="AccessibleObject.Help"]/*' />
        /// <devdoc>
        ///    <para>Gets a description of what the object does or how the object is used.</para>
        /// </devdoc>
        public virtual string Help {
            get {
                if (systemIAccessible != null) {
                    try {
                        return systemIAccessible.get_accHelp(NativeMethods.CHILDID_SELF);
                    }
                    catch (COMException e) {
                        if (e.ErrorCode != NativeMethods.DISP_E_MEMBERNOTFOUND) {
                            throw e;
                        }
                    }
                }
                return null;
            }
        } 
        
        /// <include file='doc\AccessibleObject.uex' path='docs/doc[@for="AccessibleObject.KeyboardShortcut"]/*' />
        /// <devdoc>
        ///    <para>Gets the object shortcut key or access key
        ///       for an accessible object.</para>
        /// </devdoc>
        public virtual string KeyboardShortcut {
            get {
                if (systemIAccessible != null) {
                    try {
                        return systemIAccessible.get_accKeyboardShortcut(NativeMethods.CHILDID_SELF);
                    }
                    catch (COMException e) {
                        if (e.ErrorCode != NativeMethods.DISP_E_MEMBERNOTFOUND) {
                            throw e;
                        }
                    }
                }
                return null;
            }
        } 
         
        /// <include file='doc\AccessibleObject.uex' path='docs/doc[@for="AccessibleObject.Name"]/*' />
        /// <devdoc>
        ///    <para>Gets
        ///       or sets the object name.</para>
        /// </devdoc>
        public virtual string Name {
            // Does nothing by default
            get {
                if (systemIAccessible != null) {
                    try {
                        return systemIAccessible.get_accName(NativeMethods.CHILDID_SELF);
                    }
                    catch (COMException e) {
                        if (e.ErrorCode != NativeMethods.DISP_E_MEMBERNOTFOUND) {
                            throw e;
                        }
                    }
                }
                return null;
            }
            
            set {
                if (systemIAccessible != null) {
                    try {
                        systemIAccessible.set_accName(NativeMethods.CHILDID_SELF, value);
                    }
                    catch (COMException e) {
                        if (e.ErrorCode != NativeMethods.DISP_E_MEMBERNOTFOUND) {
                            throw e;
                        }
                    }
                }
            
            }
        }
 
        /// <include file='doc\AccessibleObject.uex' path='docs/doc[@for="AccessibleObject.Parent"]/*' />
        /// <devdoc>
        ///    <para>When overridden in a derived class, gets or sets the parent of an accessible object.</para>
        /// </devdoc>
        public virtual AccessibleObject Parent {
            [SecurityPermission(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)]
            get {
                if (systemIAccessible != null) {
                    return WrapIAccessible(systemIAccessible.accParent);
                }
                else {
                    return null;
                }
            }
        }
 
        /// <include file='doc\AccessibleObject.uex' path='docs/doc[@for="AccessibleObject.Role"]/*' />
        /// <devdoc>
        ///    <para>Gets the role of this accessible object.</para>
        /// </devdoc>
        public virtual AccessibleRole Role {
            get {
                if (systemIAccessible != null) {
                    return (AccessibleRole) systemIAccessible.get_accRole(NativeMethods.CHILDID_SELF);
                }
                else {
                    return AccessibleRole.None;
                }                
            }
        }
        
        /// <include file='doc\AccessibleObject.uex' path='docs/doc[@for="AccessibleObject.State"]/*' />
        /// <devdoc>
        ///    <para>Gets
        ///       the state of this accessible object.</para>
        /// </devdoc>
        public virtual AccessibleStates State {
            get {
                if (systemIAccessible != null) {
                    return (AccessibleStates) systemIAccessible.get_accState(NativeMethods.CHILDID_SELF);
                }
                else {
                    return AccessibleStates.None;
                }
            }
        }
 
        /// <include file='doc\AccessibleObject.uex' path='docs/doc[@for="AccessibleObject.Value"]/*' />
        /// <devdoc>
        ///    <para>Gets or sets the value of an accessible object.</para>
        /// </devdoc>
        public virtual string Value {
            // Does nothing by default
            [SecurityPermission(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)]
            get {
                if (systemIAccessible != null) {
                    try {
                        return systemIAccessible.get_accValue(NativeMethods.CHILDID_SELF);
                    }
                    catch (COMException e) {
                        if (e.ErrorCode != NativeMethods.DISP_E_MEMBERNOTFOUND) {
                            throw e;
                        }
                    }
                }
                return "";
            }
 
            [SecurityPermission(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)]
            set {
                if (systemIAccessible != null) {
                    try {
                        systemIAccessible.set_accValue(NativeMethods.CHILDID_SELF, value);
                    }
                    catch (COMException e) {
                        if (e.ErrorCode != NativeMethods.DISP_E_MEMBERNOTFOUND) {
                            throw e;
                        }
                    }
                }                    
            }
        }
 
        // Methods
 
        /// <include file='doc\AccessibleObject.uex' path='docs/doc[@for="AccessibleObject.GetChild"]/*' />
        /// <devdoc>
        ///    <para>When overridden in a derived class, gets the accessible child corresponding to the specified 
        ///       index.</para>
        /// </devdoc>
        public virtual AccessibleObject GetChild(int index) {
            return null;
        }
        
        /// <include file='doc\AccessibleObject.uex' path='docs/doc[@for="AccessibleObject.GetChildCount"]/*' />
        /// <devdoc>
        ///    <para> When overridden in a derived class, gets the number of children
        ///       belonging to an accessible object.</para>
        /// </devdoc>
        public virtual int GetChildCount() {
            return -1;
        }
 
        /// <internalonly/>
        /// <devdoc>
        ///     Mechanism for overriding default IEnumVariant behavior of the 'inner' system accessible object
        ///     (IEnumVariant is how a system accessible object exposes its ordered list of child objects).
        ///
        ///     USAGE: Overridden method in derived class should return array of integers representing new order
        ///     to be imposed on the child accessible object collection returned by the system (which
        ///     we assume will be a set of accessible objects that represent the child windows, in
        ///     z-order). Each array element contains the original z-order based rank of the child window
        ///     that is to appear at that position in the new ordering. Note: This array could also be
        ///     used to filter out unwanted child windows too, if necessary (not recommended).
        /// </devdoc>
        internal virtual int[] GetSysChildOrder() {
            return null;
        }
 
        /// <internalonly/>
        /// <devdoc>
        ///     Mechanism for overriding default IAccessible.accNavigate behavior of the 'inner' system accessible
        ///     object (accNavigate is how you move between parent, child and sibling accessible objects).
        ///
        ///     USAGE: 'navdir' indicates navigation operation to perform, relative to this accessible object.
        ///     If operation is unsupported, return false to allow fall-back to default system behavior. Otherwise
        ///     return destination object in the out parameter, or null to indicate 'off end of list'.
        /// </devdoc>
        internal virtual bool GetSysChild(AccessibleNavigation navdir, out AccessibleObject accessibleObject) {
            accessibleObject = null;
            return false;
        }
 
        /// <include file='doc\AccessibleObject.uex' path='docs/doc[@for="AccessibleObject.GetFocused"]/*' />
        /// <devdoc>
        ///    <para> When overridden in a derived class,
        ///       gets the object that has the keyboard focus.</para>
        /// </devdoc>
        public virtual AccessibleObject GetFocused() {
        
            // Default behavior for objects with AccessibleObject children
            //
            if (GetChildCount() >= 0) {
                int count = GetChildCount();
                for(int index=0; index < count; ++index) {
                    AccessibleObject child = GetChild(index);
                    Debug.Assert(child != null, "GetChild(" + index.ToString(CultureInfo.InvariantCulture) + ") returned null!");
                    if (child != null && ((child.State & AccessibleStates.Focused) != 0)) {
                        return child;
                    }
                }
                if ((this.State & AccessibleStates.Focused) != 0) {
                    return this;
                }
                return null;
            }
        
            if (systemIAccessible != null) {
                try {
                    return WrapIAccessible(systemIAccessible.accFocus);
                }
                catch (COMException e) {
                    if (e.ErrorCode != NativeMethods.DISP_E_MEMBERNOTFOUND) {
                        throw e;
                    }
                }
            }
 
            return null;
        }
        
        /// <include file='doc\AccessibleObject.uex' path='docs/doc[@for="AccessibleObject.GetHelpTopic"]/*' />
        /// <devdoc>
        ///    <para> 
        ///       Gets an identifier for a Help topic and the path to the Help file associated
        ///       with this accessible object.</para>
        /// </devdoc>
        public virtual int GetHelpTopic(out string fileName) {
            if (systemIAccessible != null) {
                try {
                    int retVal = systemIAccessible.get_accHelpTopic(out fileName, NativeMethods.CHILDID_SELF);
                    if (fileName != null && fileName.Length > 0) {
                        IntSecurity.DemandFileIO(FileIOPermissionAccess.PathDiscovery, fileName);
                    }
                    return retVal;
                }
                catch (COMException e) {
                    if (e.ErrorCode != NativeMethods.DISP_E_MEMBERNOTFOUND) {
                        throw e;
                    }
                }                
            } 
            fileName = null;
            return -1;
        }
        
        /// <include file='doc\AccessibleObject.uex' path='docs/doc[@for="AccessibleObject.GetSelected"]/*' />
        /// <devdoc>
        ///    <para> When overridden in
        ///       a derived class, gets the currently selected child.</para>
        /// </devdoc>
        public virtual AccessibleObject GetSelected() {
            // Default behavior for objects with AccessibleObject children
            //
            if (GetChildCount() >= 0) {
                int count = GetChildCount();
                for(int index=0; index < count; ++index) {
                    AccessibleObject child = GetChild(index);
                    Debug.Assert(child != null, "GetChild(" + index.ToString(CultureInfo.InvariantCulture) + ") returned null!");
                    if (child != null && ((child.State & AccessibleStates.Selected) != 0)) {
                        return child;
                    }
                }
                if ((this.State & AccessibleStates.Selected) != 0) {
                    return this;
                }
                return null;
            }
        
            if (systemIAccessible != null) {
                try {
                    return WrapIAccessible(systemIAccessible.accSelection);
                }
                catch (COMException e) {
                    if (e.ErrorCode != NativeMethods.DISP_E_MEMBERNOTFOUND) {
                        throw e;
                    }
                }
            }
 
            return null;
        }
        
        /// <include file='doc\AccessibleObject.uex' path='docs/doc[@for="AccessibleObject.HitTest"]/*' />
        /// <devdoc>
        ///    <para>Return the child object at the given screen coordinates.</para>
        /// </devdoc>
        public virtual AccessibleObject HitTest(int x, int y) {
        
            // Default behavior for objects with AccessibleObject children
            //
            if (GetChildCount() >= 0) {
                int count = GetChildCount();
                for(int index=0; index < count; ++index) {
                    AccessibleObject child = GetChild(index);
                    Debug.Assert(child != null, "GetChild(" + index.ToString(CultureInfo.InvariantCulture) + ") returned null!");
                    if (child != null && child.Bounds.Contains(x, y)) {
                        return child;
                    }
                }
                return this;
            }
            
            if (systemIAccessible != null) {
                try {
                    return WrapIAccessible(systemIAccessible.accHitTest(x, y));
                }
                catch (COMException e) {
                    if (e.ErrorCode != NativeMethods.DISP_E_MEMBERNOTFOUND) {
                        throw e;
                    }
                }
            }
            
            if (this.Bounds.Contains(x, y)) {
                return this;
            }
            
            return null;
        }
 
        //
        // UIAutomation support helpers
        //
 
        internal virtual bool IsIAccessibleExSupported() {
            // Override this, in your derived class, to enable IAccessibleEx support
            return false;
        }
 
        internal virtual bool IsPatternSupported(int patternId) {
            // Override this, in your derived class, if you implement UIAutomation patterns 
 
            if (AccessibilityImprovements.Level3 && patternId == NativeMethods.UIA_InvokePatternId) {
                return IsInvokePatternAvailable;
            }
 
            return false;
        }
 
        //
        // Overridable methods for IRawElementProviderSimple interface
        //
 
        internal virtual int[] RuntimeId {
            get {
                return null;
            }
        }
 
        internal virtual int ProviderOptions {
            get {
                return (int)(UnsafeNativeMethods.ProviderOptions.ServerSideProvider | UnsafeNativeMethods.ProviderOptions.UseComThreading);
            }
        }
 
        internal virtual UnsafeNativeMethods.IRawElementProviderSimple HostRawElementProvider {
            get {
                return null;
            }
        }
 
        internal virtual object GetPropertyValue(int propertyID) {
            if (AccessibilityImprovements.Level3 && propertyID == NativeMethods.UIA_IsInvokePatternAvailablePropertyId) {
                return IsInvokePatternAvailable;
            }
 
            return null;
        }
 
        private bool IsInvokePatternAvailable {
            get {
                // MSAA Proxy determines the availability of invoke pattern based on Role/DefaultAction properties.
                // Below code emulates the same rules.
                switch (Role) {
                    case AccessibleRole.MenuItem:
                    case AccessibleRole.Link:
                    case AccessibleRole.PushButton:
                    case AccessibleRole.ButtonDropDown:
                    case AccessibleRole.ButtonMenu:
                    case AccessibleRole.ButtonDropDownGrid:
                    case AccessibleRole.Clock:
                    case AccessibleRole.SplitButton:
                        return true;
 
                    case AccessibleRole.Default:
                    case AccessibleRole.None:
                    case AccessibleRole.Sound:
                    case AccessibleRole.Cursor:
                    case AccessibleRole.Caret:
                    case AccessibleRole.Alert:
                    case AccessibleRole.Client:
                    case AccessibleRole.Chart:
                    case AccessibleRole.Dialog:
                    case AccessibleRole.Border:
                    case AccessibleRole.Column:
                    case AccessibleRole.Row:
                    case AccessibleRole.HelpBalloon:
                    case AccessibleRole.Character:
                    case AccessibleRole.PageTab:
                    case AccessibleRole.PropertyPage:
                    case AccessibleRole.DropList:
                    case AccessibleRole.Dial:
                    case AccessibleRole.HotkeyField:
                    case AccessibleRole.Diagram:
                    case AccessibleRole.Animation:
                    case AccessibleRole.Equation:
                    case AccessibleRole.WhiteSpace:
                    case AccessibleRole.IpAddress:
                    case AccessibleRole.OutlineButton:
                        return false;
 
                    default:
                        return !string.IsNullOrEmpty(DefaultAction);
                }
            }
        }
 
        //
        // Overridable methods for ILegacyAccessible interface
        //
 
        internal virtual int GetChildId() {
            return NativeMethods.CHILDID_SELF;
        }
 
        //
        // Overridable methods for IRawElementProviderFragment interface
        //
 
        internal virtual UnsafeNativeMethods.IRawElementProviderFragment FragmentNavigate(UnsafeNativeMethods.NavigateDirection direction) {
            return null;
        }
 
        internal virtual UnsafeNativeMethods.IRawElementProviderSimple[] GetEmbeddedFragmentRoots() {
            return null;
        }
 
        internal virtual void SetFocus() {
        }
 
        internal virtual Rectangle BoundingRectangle {
            get {
                return this.Bounds;
            }
        }
 
        internal virtual UnsafeNativeMethods.IRawElementProviderFragmentRoot FragmentRoot {
            get {
                return null;
            }
        }
 
        //
        // Overridable methods for IRawElementProviderFragmentRoot interface
        //
 
        internal virtual UnsafeNativeMethods.IRawElementProviderFragment ElementProviderFromPoint(double x, double y) {
            return this;
        }
 
        internal virtual UnsafeNativeMethods.IRawElementProviderFragment GetFocus() {
            return null;
        }
 
        //
        // Overridable methods for IExpandCollapseProvider pattern interface
        //
 
        internal virtual void Expand() {
        }
 
        internal virtual void Collapse() {
        }
 
        internal virtual UnsafeNativeMethods.ExpandCollapseState ExpandCollapseState {
            get {
                return UnsafeNativeMethods.ExpandCollapseState.Collapsed;
            }
        }
 
        //
        // Overridable methods for IToggleProvider pattern interface
        //
 
        internal virtual void Toggle() {
        }
 
        internal virtual UnsafeNativeMethods.ToggleState ToggleState {
            get {
                return UnsafeNativeMethods.ToggleState.ToggleState_Indeterminate;
            }
        }
 
        //
        // Overridable methods for ITableProvider pattern interface
        //
 
        internal virtual UnsafeNativeMethods.IRawElementProviderSimple[] GetRowHeaders() {
            return null;
        }
 
        internal virtual UnsafeNativeMethods.IRawElementProviderSimple[] GetColumnHeaders() {
            return null;
        }
 
        internal virtual UnsafeNativeMethods.RowOrColumnMajor RowOrColumnMajor {
            get {
                return UnsafeNativeMethods.RowOrColumnMajor.RowOrColumnMajor_RowMajor;
            }
        }
 
        //
        // Overridable methods for ITableItemProvider pattern interface
        //
 
        internal virtual UnsafeNativeMethods.IRawElementProviderSimple[] GetRowHeaderItems() {
            return null;
        }
 
        internal virtual UnsafeNativeMethods.IRawElementProviderSimple[] GetColumnHeaderItems() {
            return null;
        }
 
        //
        // Overridable methods for IGridProvider pattern interface
        //
 
        internal virtual UnsafeNativeMethods.IRawElementProviderSimple GetItem(int row, int column) {
            return null;
        }
 
        internal virtual int RowCount {
            get {
                return -1;
            }
        }
 
        internal virtual int ColumnCount {
            get {
                return -1;
            }
        }
 
        //
        // Overridable methods for IGridItemProvider pattern interface
        //
        
        internal virtual int Row {
            get {
                return -1;
            }
        }
 
        internal virtual int Column {
            get {
                return -1;
            }
        }
 
        internal virtual int RowSpan {
            get {
                return 1;
            }
        }
 
        internal virtual int ColumnSpan {
            get {
                return 1;
            }
        }
 
        internal virtual UnsafeNativeMethods.IRawElementProviderSimple ContainingGrid {
            get {
                return null;
            }
        }
 
        //
        // Overridable methods for IInvokeProvider pattern interface
        //
 
        internal virtual void Invoke() {
            // Calling DoDefaultAction here is consistent with MSAA Proxy implementation.
            DoDefaultAction();
        }
 
        // Overridable methods for IValueProvider pattern interface
 
        internal virtual bool IsReadOnly {
            get {
                return false;
            }
        }
 
        internal virtual void SetValue(string newValue) {
            this.Value = newValue;
        }
 
        //
        // Overridable methods for IRawElementProviderHwndOverride interface
        //
 
        internal virtual UnsafeNativeMethods.IRawElementProviderSimple GetOverrideProviderForHwnd(IntPtr hwnd) {
            return null;
        }
 
        //
        // Overridable methods for IRangeValueProvider pattern interface
        //
 
        internal virtual void SetValue(double newValue) {
        }
 
        internal virtual double LargeChange {
            get {
                return double.NaN;
            }
        }
 
        internal virtual double Maximum {
            get {
                return double.NaN;
            }
        }
 
        internal virtual double Minimum {
            get {
                return double.NaN;
            }
        }
 
        internal virtual double SmallChange {
            get {
                return double.NaN;
            }
        }
 
        internal virtual double RangeValue {
            get {
                return double.NaN;
            }
        }
 
        //
        // Overridable methods for ISelectionProvider interface
        //
 
        internal virtual UnsafeNativeMethods.IRawElementProviderSimple[] GetSelection() {
            return null;
        }
 
        internal virtual bool CanSelectMultiple {
            get {
                return false;
            }
        }
 
        internal virtual bool IsSelectionRequired {
            get {
                return false;
            }
        }
 
        //
        // Overridable methods for ISelectionItemProvider interface
        //
 
        internal virtual void SelectItem() {
        }
 
        internal virtual void AddToSelection() {
        }
 
        internal virtual void RemoveFromSelection() {
        }
 
        internal virtual bool IsItemSelected {
            get {
                return false;
            }
        }
 
        internal virtual UnsafeNativeMethods.IRawElementProviderSimple ItemSelectionContainer {
            get {
                return null;
            }
        }
 
        /// <summary>
        /// Sets the parent accessible object for the node which can be added or removed to/from hierachy nodes.
        /// </summary>
        /// <param name="parent">The parent accessible object.</param>
        internal virtual void SetParent(AccessibleObject parent)
        {
        }
 
        /// <summary>
        /// Sets the detachable child accessible object which may be added or removed to/from hierachy nodes.
        /// </summary>
        /// <param name="child">The child accessible object.</param>
        internal virtual void SetDetachableChild(AccessibleObject child)
        {
        }
 
        int UnsafeNativeMethods.IServiceProvider.QueryService(ref Guid service, ref Guid riid, out IntPtr ppvObject) {
 
            int hr = NativeMethods.E_NOINTERFACE;
            ppvObject = IntPtr.Zero;
 
            if (IsIAccessibleExSupported()) {
                if (service.Equals(UnsafeNativeMethods.guid_IAccessibleEx) &&
                    riid.Equals(UnsafeNativeMethods.guid_IAccessibleEx)) {
                    // We want to return the internal, secure, object, which we don't have access here
                    // Return non-null, which will be interpreted in internal method, to mean returning casted object to IAccessibleEx
 
                    ppvObject = Marshal.GetComInterfaceForObject(this, typeof(UnsafeNativeMethods.IAccessibleEx));
                    hr = NativeMethods.S_OK;
                }
            }
 
            return hr;
        }
 
        object UnsafeNativeMethods.IAccessibleEx.GetObjectForChild(int childId) {
            return GetObjectForChild(childId);
        }
 
        internal virtual object GetObjectForChild(int childId) {
            return null;
        }
 
        // This method is never called
        int UnsafeNativeMethods.IAccessibleEx.GetIAccessiblePair(out object ppAcc, out int pidChild) {
 
            // No need to implement this for patterns and properties
            ppAcc = null;
            pidChild = 0;
            return NativeMethods.E_POINTER;
        }
 
        int[] UnsafeNativeMethods.IAccessibleEx.GetRuntimeId() {
            return RuntimeId;
        }
 
        int UnsafeNativeMethods.IAccessibleEx.ConvertReturnedElement(object pIn, out object ppRetValOut) {
 
            // No need to implement this for patterns and properties
            ppRetValOut = null;
            return NativeMethods.E_NOTIMPL;
        }
 
        //
        // IRawElementProviderSimple interface
        //
 
        UnsafeNativeMethods.ProviderOptions UnsafeNativeMethods.IRawElementProviderSimple.ProviderOptions {
            get {
                return (UnsafeNativeMethods.ProviderOptions) ProviderOptions;
            }
        }
 
        UnsafeNativeMethods.IRawElementProviderSimple UnsafeNativeMethods.IRawElementProviderSimple.HostRawElementProvider {
            get {
                return HostRawElementProvider;
            }
        }
 
        object UnsafeNativeMethods.IRawElementProviderSimple.GetPatternProvider(int patternId) {
            if (IsPatternSupported(patternId)) {
                return this;
            }
            else {
                return null;
            }
        }
 
        object UnsafeNativeMethods.IRawElementProviderSimple.GetPropertyValue(int propertyID) {
            return GetPropertyValue(propertyID);
        }
 
        //
        // IRawElementProviderFragment interface
        //
 
        object UnsafeNativeMethods.IRawElementProviderFragment.Navigate(UnsafeNativeMethods.NavigateDirection direction) {
            return FragmentNavigate(direction);
        }
 
        int[] UnsafeNativeMethods.IRawElementProviderFragment.GetRuntimeId() {
            return RuntimeId;
        }
 
        object[] UnsafeNativeMethods.IRawElementProviderFragment.GetEmbeddedFragmentRoots() {
            return GetEmbeddedFragmentRoots();
        }
 
        void UnsafeNativeMethods.IRawElementProviderFragment.SetFocus() {
            SetFocus();
        }
 
        NativeMethods.UiaRect UnsafeNativeMethods.IRawElementProviderFragment.BoundingRectangle {
            get {
                return new NativeMethods.UiaRect(BoundingRectangle);
            }
        }
 
        UnsafeNativeMethods.IRawElementProviderFragmentRoot UnsafeNativeMethods.IRawElementProviderFragment.FragmentRoot {
            get {
                return FragmentRoot;
            }
        }
 
        //
        // IRawElementProviderFragmentRoot interface
        //
 
        object UnsafeNativeMethods.IRawElementProviderFragmentRoot.ElementProviderFromPoint(double x, double y) {
            return ElementProviderFromPoint(x, y);
        }
 
        object UnsafeNativeMethods.IRawElementProviderFragmentRoot.GetFocus() {
            return GetFocus();
        }
 
        //
        // ILegacyIAccessibleProvider interface
        //
 
        string UnsafeNativeMethods.ILegacyIAccessibleProvider.DefaultAction {
            get {
                return this.DefaultAction;
            }
        }
 
        string UnsafeNativeMethods.ILegacyIAccessibleProvider.Description {
            get {
                return this.Description;
            }
        }
 
        string UnsafeNativeMethods.ILegacyIAccessibleProvider.Help {
            get {
                return this.Help;
            }
        }
 
        string UnsafeNativeMethods.ILegacyIAccessibleProvider.KeyboardShortcut {
            get {
                return this.KeyboardShortcut;
            }
        }
 
        string UnsafeNativeMethods.ILegacyIAccessibleProvider.Name {
            get {
                return this.Name;
            }
        }
 
        uint UnsafeNativeMethods.ILegacyIAccessibleProvider.Role {
            get {
                return (uint)this.Role;
            }
        }
 
        uint UnsafeNativeMethods.ILegacyIAccessibleProvider.State {
            get {
                return (uint)this.State;
            }
        }
 
        string UnsafeNativeMethods.ILegacyIAccessibleProvider.Value {
            get {
                return this.Value;
            }
        }
 
        int UnsafeNativeMethods.ILegacyIAccessibleProvider.ChildId {
            get {
                return GetChildId();
            }
        }
 
        void UnsafeNativeMethods.ILegacyIAccessibleProvider.DoDefaultAction() {
            this.DoDefaultAction();
        }
 
        IAccessible UnsafeNativeMethods.ILegacyIAccessibleProvider.GetIAccessible() {
            return this.AsIAccessible(this);
        }
 
        object[] UnsafeNativeMethods.ILegacyIAccessibleProvider.GetSelection() {
            return new UnsafeNativeMethods.IRawElementProviderSimple[] {
                this.GetSelected() as UnsafeNativeMethods.IRawElementProviderSimple
            };
        }
 
        void UnsafeNativeMethods.ILegacyIAccessibleProvider.Select(int flagsSelect) {
            this.Select((AccessibleSelection)flagsSelect);
        }
 
        void UnsafeNativeMethods.ILegacyIAccessibleProvider.SetValue(string szValue) {
            this.SetValue(szValue);
        }
 
        //
        // IExpandCollapseProvider interface
        //
 
        void UnsafeNativeMethods.IExpandCollapseProvider.Expand() {
            Expand();
        }
        void UnsafeNativeMethods.IExpandCollapseProvider.Collapse() {
            Collapse();
        }
 
        UnsafeNativeMethods.ExpandCollapseState UnsafeNativeMethods.IExpandCollapseProvider.ExpandCollapseState {
            get {
                return ExpandCollapseState;
            }
        }
 
        //
        // IInvokeProvider interface
        //
 
        void UnsafeNativeMethods.IInvokeProvider.Invoke() {
            Invoke();
        }
 
        //
        // IValueProvider interface
        //
 
        bool UnsafeNativeMethods.IValueProvider.IsReadOnly {
            get {
                return IsReadOnly;
            }
        }
 
        string UnsafeNativeMethods.IValueProvider.Value {
            get {
                return Value;
            }
        }
 
        void UnsafeNativeMethods.IValueProvider.SetValue(string newValue) {
            SetValue(newValue);
        }
 
        //
        // IToggleProvider implementation
        //
 
        void UnsafeNativeMethods.IToggleProvider.Toggle() {
            Toggle();
        }
 
        UnsafeNativeMethods.ToggleState UnsafeNativeMethods.IToggleProvider.ToggleState {
            get {
                return ToggleState;
            }
        }
 
        //
        // ITableProvider implementation
        //
 
        object[] UnsafeNativeMethods.ITableProvider.GetRowHeaders() {
            return GetRowHeaders();
        }
 
        object[] UnsafeNativeMethods.ITableProvider.GetColumnHeaders() {
            return GetColumnHeaders();
        }
 
        UnsafeNativeMethods.RowOrColumnMajor UnsafeNativeMethods.ITableProvider.RowOrColumnMajor {
            get {
                return RowOrColumnMajor;
            }
        }
 
        //
        // ITableItemProvider implementation
        //
 
        object[] UnsafeNativeMethods.ITableItemProvider.GetRowHeaderItems() {
            return GetRowHeaderItems();
        }
 
        object[] UnsafeNativeMethods.ITableItemProvider.GetColumnHeaderItems() {
            return GetColumnHeaderItems();
        }
 
        //
        // IGridProvider implementation
        //
 
        object UnsafeNativeMethods.IGridProvider.GetItem(int row, int column) {
            return GetItem(row, column);
        }
 
        int UnsafeNativeMethods.IGridProvider.RowCount {
            get {
                return RowCount;
            }
        }
 
        int UnsafeNativeMethods.IGridProvider.ColumnCount {
            get {
                return ColumnCount;
            }
        }
 
        //
        // IGridItemProvider implementation
        //
        
        int UnsafeNativeMethods.IGridItemProvider.Row {
            get {
                return Row;
            }
        }
 
        int UnsafeNativeMethods.IGridItemProvider.Column {
            get {
                return Column;
            }
        }
 
        int UnsafeNativeMethods.IGridItemProvider.RowSpan {
            get {
                return RowSpan;
            }
        }
 
        int UnsafeNativeMethods.IGridItemProvider.ColumnSpan {
            get {
                return ColumnSpan;
            }
        }
 
        UnsafeNativeMethods.IRawElementProviderSimple UnsafeNativeMethods.IGridItemProvider.ContainingGrid {
            get {
                return ContainingGrid;
            }
        }
 
        /// <include file='doc\AccessibleObject.uex' path='docs/doc[@for="AccessibleObject.IAccessible.accDoDefaultAction"]/*' />
        /// <internalonly/>
        /// <devdoc>
        /// <para>
        /// Perform the default action
        /// </para>
        /// </devdoc>
        void IAccessible.accDoDefaultAction(Object childID) {
 
            IntSecurity.UnmanagedCode.Demand();
 
            if (IsClientObject) {
                ValidateChildID(ref childID);
                
                Debug.WriteLineIf(CompModSwitches.MSAA.TraceInfo, "AccessibleObject.AccDoDefaultAction: this = " + 
                    this.ToString() + ", childID = " + childID.ToString());
 
                // If the default action is to be performed on self, do it.
                if (childID.Equals(NativeMethods.CHILDID_SELF)) {
                    DoDefaultAction();
                    return;
                }
                    
                // If we have an accessible object collection, get the appropriate child
                AccessibleObject child = GetAccessibleChild(childID);
                if (child != null) {
                    child.DoDefaultAction();
                    return;
                }            
            }
 
            if (systemIAccessible != null) {
                try {
                    systemIAccessible.accDoDefaultAction(childID);
                }
                catch (COMException e) {
                    // Not all objects provide a default action
                    //
                    if (e.ErrorCode != NativeMethods.DISP_E_MEMBERNOTFOUND) {
                        throw e;
                    }
                }
            }
        }
 
        /// <include file='doc\AccessibleObject.uex' path='docs/doc[@for="AccessibleObject.IAccessible.accHitTest"]/*' />
        /// <internalonly/>
        /// <devdoc>
        /// <para>
        /// Perform a hit test
        /// </para>
        /// </devdoc>
        Object IAccessible.accHitTest(
                                 int xLeft,
                                 int yTop) {
 
            if (IsClientObject) {
                Debug.WriteLineIf(CompModSwitches.MSAA.TraceInfo, "AccessibleObject.AccHitTest: this = " + 
                    this.ToString());
                
                AccessibleObject obj = HitTest(xLeft, yTop);
                if (obj != null) {
                    return AsVariant(obj);
                }
            }
 
            if (systemIAccessible != null) {
                try {
                    return systemIAccessible.accHitTest(xLeft, yTop);
                }
                catch (COMException e) {
                    if (e.ErrorCode != NativeMethods.DISP_E_MEMBERNOTFOUND) {
                        throw e;
                    }
                }
            }
            
            return null;
        }
 
        /// <include file='doc\AccessibleObject.uex' path='docs/doc[@for="AccessibleObject.IAccessible.accLocation"]/*' />
        /// <internalonly/>
        /// <devdoc>
        /// <para>
        /// The location of the Accessible object
        /// </para>
        /// </devdoc>
        void IAccessible.accLocation(
                               out int pxLeft,
                               out int pyTop,
                               out int pcxWidth,
                               out int pcyHeight,
                               Object childID) {
            
            pxLeft = 0;
            pyTop = 0;
            pcxWidth = 0;
            pcyHeight = 0;
 
            if (IsClientObject) {
                ValidateChildID(ref childID);
                
                Debug.WriteLineIf(CompModSwitches.MSAA.TraceInfo, "AccessibleObject.AccLocation: this = " + 
                    this.ToString() + ", childID = " + childID.ToString());
 
                // Use the Location function's return value if available            
                //
                if (childID.Equals(NativeMethods.CHILDID_SELF)) {
                    Rectangle bounds = this.Bounds;
                    pxLeft = bounds.X;
                    pyTop = bounds.Y;
                    pcxWidth = bounds.Width;
                    pcyHeight = bounds.Height;
                    
                    Debug.WriteLineIf(CompModSwitches.MSAA.TraceInfo, "AccessibleObject.AccLocation: Returning " + 
                        bounds.ToString());
                    
                    return;
                }
                
                // If we have an accessible object collection, get the appropriate child
                //
                AccessibleObject child = GetAccessibleChild(childID);
                if (child != null) {
                    Rectangle bounds = child.Bounds;
                    pxLeft = bounds.X;
                    pyTop = bounds.Y;
                    pcxWidth = bounds.Width;
                    pcyHeight = bounds.Height;
                    
                    Debug.WriteLineIf(CompModSwitches.MSAA.TraceInfo, "AccessibleObject.AccLocation: Returning " + 
                        bounds.ToString());
                    
                    return;
                }
            }
 
            if (systemIAccessible != null) {
                try {
                    systemIAccessible.accLocation(out pxLeft, out pyTop, out pcxWidth, out pcyHeight, childID);
 
                    Debug.WriteLineIf(CompModSwitches.MSAA.TraceInfo, "AccessibleObject.AccLocation: Setting " + 
                        pxLeft.ToString(CultureInfo.InvariantCulture) + ", " +
                        pyTop.ToString(CultureInfo.InvariantCulture) + ", " +
                        pcxWidth.ToString(CultureInfo.InvariantCulture) + ", " +
                        pcyHeight.ToString(CultureInfo.InvariantCulture));
                }
                catch (COMException e) {
                    if (e.ErrorCode != NativeMethods.DISP_E_MEMBERNOTFOUND) {
                        throw e;
                    }
                }
                
                return;
            }
        }
 
        /// <include file='doc\AccessibleObject.uex' path='docs/doc[@for="AccessibleObject.IAccessible.accNavigate"]/*' />
        /// <internalonly/>
        /// <devdoc>
        /// <para>
        /// Navigate to another accessible object.
        /// </para>
        /// </devdoc>
        Object IAccessible.accNavigate(
                                  int navDir,
                                  Object childID) {
 
            IntSecurity.UnmanagedCode.Demand();
 
            if (IsClientObject) {
                ValidateChildID(ref childID);
 
                Debug.WriteLineIf(CompModSwitches.MSAA.TraceInfo, "AccessibleObject.AccNavigate: this = " +
                    this.ToString() + ", navdir = " + navDir.ToString(CultureInfo.InvariantCulture) + ", childID = " + childID.ToString());
                               
                // Use the Navigate function's return value if available            
                //
                if (childID.Equals(NativeMethods.CHILDID_SELF)) {
                    AccessibleObject newObject = Navigate((AccessibleNavigation)navDir);
                    if (newObject != null) {
                        return AsVariant(newObject);
                    }
                }
                
                // If we have an accessible object collection, get the appropriate child
                AccessibleObject child = GetAccessibleChild(childID);
                if (child != null) {
                    return AsVariant(child.Navigate((AccessibleNavigation)navDir));
                }
            }
 
            if (systemIAccessible != null) {
                try {
                    Object retObject;
                    if (!SysNavigate(navDir, childID, out retObject))
                        retObject = systemIAccessible.accNavigate(navDir, childID);
                    return retObject;
                }
                catch (COMException e) {
                    if (e.ErrorCode != NativeMethods.DISP_E_MEMBERNOTFOUND) {
                        throw e;
                    }
                }
            }
 
            return null;
        }
 
        /// <include file='doc\AccessibleObject.uex' path='docs/doc[@for="AccessibleObject.IAccessible.accSelect"]/*' />
        /// <internalonly/>
        /// <devdoc>
        /// <para>
        /// Select an accessible object.
        /// </para>
        /// </devdoc>
        void IAccessible.accSelect(int flagsSelect, Object childID) {
 
            IntSecurity.UnmanagedCode.Demand();
 
            if (IsClientObject) {
                ValidateChildID(ref childID);
 
                Debug.WriteLineIf(CompModSwitches.MSAA.TraceInfo, "AccessibleObject.AccSelect: this = " +
                    this.ToString() + ", flagsSelect = " + flagsSelect.ToString(CultureInfo.InvariantCulture) + ", childID = " + childID.ToString());
                
                // If the selection is self, do it.
                if (childID.Equals(NativeMethods.CHILDID_SELF)) {
                    Select((AccessibleSelection)flagsSelect);    // Uses an Enum which matches SELFLAG
                    return;
                }
                
                // If we have an accessible object collection, get the appropriate child
                AccessibleObject child = GetAccessibleChild(childID);
                if (child != null) {
                    child.Select((AccessibleSelection)flagsSelect);
                    return;
                }
            }
 
            if (systemIAccessible != null) {
                try {
                    systemIAccessible.accSelect(flagsSelect, childID);
                }
                catch (COMException e) {
                    if (e.ErrorCode != NativeMethods.DISP_E_MEMBERNOTFOUND) {
                        throw e;
                    }
                }
                return;
            }
 
        }
 
        /// <include file='doc\AccessibleObject.uex' path='docs/doc[@for="AccessibleObject.DoDefaultAction"]/*' />
        /// <devdoc>
        ///      Performs the default action associated with this accessible object.
        /// </devdoc>
        [SecurityPermission(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)]
        public virtual void DoDefaultAction() {
            // By default, just does the system default action if available
            //
            if (systemIAccessible != null) {
                try {
                    systemIAccessible.accDoDefaultAction(0);
                }
                catch (COMException e) {
                    // Not all objects provide a default action
                    //
                    if (e.ErrorCode != NativeMethods.DISP_E_MEMBERNOTFOUND) {
                        throw e;
                    }                    
                }
                return;
            }
        }
 
        /// <include file='doc\AccessibleObject.uex' path='docs/doc[@for="AccessibleObject.IAccessible.get_accChild"]/*' />
        /// <internalonly/>
        /// <devdoc>
        /// <para>
        /// Returns a child Accessible object
        /// </para>
        /// </devdoc>
        object IAccessible.get_accChild(object childID) {
 
            if (IsClientObject) {
                ValidateChildID(ref childID);
 
                Debug.WriteLineIf(CompModSwitches.MSAA.TraceInfo, "AccessibleObject.GetAccChild: this = " + 
                    this.ToString() + ", childID = " + childID.ToString());
 
                // Return self for CHILDID_SELF
                if (childID.Equals(NativeMethods.CHILDID_SELF)) {
                    return AsIAccessible(this);
                }
 
                // If we have an accessible object collection, get the appropriate child
                AccessibleObject child = GetAccessibleChild(childID);
                if (child != null) {
                    // Make sure we're not returning ourselves as our own child
                    //
                    Debug.Assert(child != this, "An accessible object is returning itself as its own child. This can cause Accessibility client applications to hang.");
                    if (child == this) {
                        return null;
                    }
                    
                    return AsIAccessible(child);
                }
            }
 
            // Otherwise, return the default system child for this control (if any)
            if (systemIAccessible != null) {
                return systemIAccessible.get_accChild(childID);
            }
 
            return null;
        }
 
        /// <include file='doc\AccessibleObject.uex' path='docs/doc[@for="AccessibleObject.IAccessible.accChildCount"]/*' />
        /// <internalonly/>
        /// <devdoc>
        /// Return the number of children
        /// </devdoc>
        int IAccessible.accChildCount {
            get {
                int childCount = -1;
 
                if (IsClientObject) {
                    childCount = GetChildCount();
                }
 
                if (childCount == -1) {
                    if (systemIAccessible != null) {
                        childCount = systemIAccessible.accChildCount;
                    }
                    else {
                        childCount = 0;
                    }
                }
                
                Debug.WriteLineIf(CompModSwitches.MSAA.TraceInfo, "AccessibleObject.accHildCount: this = " + this.ToString() + ", returning " + childCount.ToString(CultureInfo.InvariantCulture));    
                
                return childCount;                
            }
        }
 
        /// <include file='doc\AccessibleObject.uex' path='docs/doc[@for="AccessibleObject.IAccessible.get_accDefaultAction"]/*' />
        /// <internalonly/>
        /// <devdoc>
        /// <para>
        /// Return the default action
        /// </para>
        /// </devdoc>
        string IAccessible.get_accDefaultAction(Object childID) {
 
            if (IsClientObject) {
                ValidateChildID(ref childID);
 
                // Return the default action property if available
                if (childID.Equals(NativeMethods.CHILDID_SELF)) {
                    return DefaultAction;
                }
                
                // If we have an accessible object collection, get the appropriate child
                AccessibleObject child = GetAccessibleChild(childID);
                if (child != null) {
                    return child.DefaultAction;
                }
            }
 
            if (systemIAccessible != null) {
                try {
                    return systemIAccessible.get_accDefaultAction(childID);
                }
                catch (COMException e) {
                    // Not all objects provide a default action
                    //
                    if (e.ErrorCode != NativeMethods.DISP_E_MEMBERNOTFOUND) {
                        throw e;
                    }
                }
            }
 
            return null;
        }
 
        /// <include file='doc\AccessibleObject.uex' path='docs/doc[@for="AccessibleObject.IAccessible.get_accDescription"]/*' />
        /// <internalonly/>
        /// <devdoc>
        /// <para>
        /// Return the object or child description
        /// </para>
        /// </devdoc>
        string IAccessible.get_accDescription(Object childID) {
 
            if (IsClientObject) {
                ValidateChildID(ref childID);
 
                // Return the description property if available
                if (childID.Equals(NativeMethods.CHILDID_SELF)) {
                    return Description;
                }
 
                // If we have an accessible object collection, get the appropriate child
                AccessibleObject child = GetAccessibleChild(childID);
                if (child != null) {
                    return child.Description;
                }
            }
 
            if (systemIAccessible != null) {
                try {
                    return systemIAccessible.get_accDescription(childID);
                }
                catch (COMException e) {
                    if (e.ErrorCode != NativeMethods.DISP_E_MEMBERNOTFOUND) {
                        throw e;
                    }
                }
            }
 
            return null;
        }
 
        /// <include file='doc\AccessibleObject.uex' path='docs/doc[@for="AccessibleObject.GetAccessibleChild"]/*' />
        /// <devdoc>
        ///      Returns the appropriate child from the Accessible Child Collection, if available
        /// </devdoc>
        private AccessibleObject GetAccessibleChild(object childID) {
            if (!childID.Equals(NativeMethods.CHILDID_SELF)) {
                int index = (int)childID - 1;   // The first child is childID == 1 (index == 0)
                if (index >= 0 && index < GetChildCount()) {
                    return GetChild(index);
                }
            }
            return null;
        }
 
        /// <include file='doc\AccessibleObject.uex' path='docs/doc[@for="AccessibleObject.IAccessible.accFocus"]/*' />
        /// <internalonly/>
        /// <devdoc>
        /// Return the object or child focus
        /// </devdoc>
        object IAccessible.accFocus {
            get {
 
                if (IsClientObject) {
                    Debug.WriteLineIf(CompModSwitches.MSAA.TraceInfo, "AccessibleObject.GetAccFocus: this = " + 
                        this.ToString());
        
                    AccessibleObject obj = GetFocused();                
                    if (obj != null) {
                        return AsVariant(obj);
                    }
                }
 
                if (systemIAccessible != null) {
                    try {
                        return systemIAccessible.accFocus;
                    }
                    catch (COMException e) {
                        if (e.ErrorCode != NativeMethods.DISP_E_MEMBERNOTFOUND) {
                            throw e;
                        }
                    }
                }
                
                return null;
            }
        }
 
        /// <include file='doc\AccessibleObject.uex' path='docs/doc[@for="AccessibleObject.IAccessible.get_accHelp"]/*' />
        /// <internalonly/>
        /// <devdoc>
        /// <para>
        /// Return help for this accessible object.
        /// </para>
        /// </devdoc>
        string IAccessible.get_accHelp(Object childID) {
 
            if (IsClientObject) {
                ValidateChildID(ref childID);
 
                if (childID.Equals(NativeMethods.CHILDID_SELF)) {
                    return Help;
                }
 
                // If we have an accessible object collection, get the appropriate child
                AccessibleObject child = GetAccessibleChild(childID);
                if (child != null) {
                    return child.Help;
                }
            }
 
            if (systemIAccessible != null) {
                try {
                    return systemIAccessible.get_accHelp(childID);
                }
                catch (COMException e) {
                    if (e.ErrorCode != NativeMethods.DISP_E_MEMBERNOTFOUND) {
                        throw e;
                    }
                }
            }
 
            return null;
        }
 
        /// <include file='doc\AccessibleObject.uex' path='docs/doc[@for="AccessibleObject.IAccessible.get_accHelpTopic"]/*' />
        /// <internalonly/>
        /// <devdoc>
        /// <para>
        /// Return the object or child help topic
        /// </para>
        /// </devdoc>
        int IAccessible.get_accHelpTopic(out string pszHelpFile, Object childID) {
 
            if (IsClientObject) {
                ValidateChildID(ref childID);
 
                if (childID.Equals(NativeMethods.CHILDID_SELF)) {
                    return GetHelpTopic(out pszHelpFile);
                }
                
                // If we have an accessible object collection, get the appropriate child
                AccessibleObject child = GetAccessibleChild(childID);
                if (child != null) {
                    return child.GetHelpTopic(out pszHelpFile);
                }
            }
 
            if (systemIAccessible != null) {
                try {
                    return systemIAccessible.get_accHelpTopic(out pszHelpFile, childID);
                }
                catch (COMException e) {
                    if (e.ErrorCode != NativeMethods.DISP_E_MEMBERNOTFOUND) {
                        throw e;
                    }
                }
            }
            
            pszHelpFile = null;
            return -1;
        }
 
        /// <include file='doc\AccessibleObject.uex' path='docs/doc[@for="AccessibleObject.IAccessible.get_accKeyboardShortcut"]/*' />
        /// <internalonly/>
        /// <devdoc>
        /// <para>
        /// Return the object or child keyboard shortcut
        /// </para>
        /// </devdoc>
        string IAccessible.get_accKeyboardShortcut(Object childID) {
            return get_accKeyboardShortcutInternal(childID);
        }
 
        internal virtual string get_accKeyboardShortcutInternal(Object childID) {
 
            if (IsClientObject) {
                ValidateChildID(ref childID);
 
                if (childID.Equals(NativeMethods.CHILDID_SELF)) {
                    return KeyboardShortcut;
                } 
                 
                // If we have an accessible object collection, get the appropriate child
                AccessibleObject child = GetAccessibleChild(childID);
                if (child != null) {
                    return child.KeyboardShortcut;
                }
            }
 
            if (systemIAccessible != null) {
                try {
                    return systemIAccessible.get_accKeyboardShortcut(childID);
                }
                catch (COMException e) {
                    if (e.ErrorCode != NativeMethods.DISP_E_MEMBERNOTFOUND) {
                        throw e;
                    }
                }
            }
 
            return null;
        }
 
        /// <include file='doc\AccessibleObject.uex' path='docs/doc[@for="AccessibleObject.IAccessible.get_accName"]/*' />
        /// <internalonly/>
        /// <devdoc>
        /// <para>
        /// Return the object or child name
        /// </para>
        /// </devdoc>
        string IAccessible.get_accName(object childID) {
            return get_accNameInternal(childID);
        }
 
        /// <devdoc>
        /// </devdoc>
        internal virtual string get_accNameInternal(object childID) {
            if (IsClientObject) {
                ValidateChildID(ref childID);
 
                Debug.WriteLineIf(CompModSwitches.MSAA.TraceInfo, "AccessibleObject.get_accName: this = " + this.ToString() + 
                    ", childID = " + childID.ToString());                                                                     
 
                // Return the name property if available
                if (childID.Equals(NativeMethods.CHILDID_SELF)) {
                    return Name;
                }
 
                // If we have an accessible object collection, get the appropriate child
                AccessibleObject child = GetAccessibleChild(childID);
                if (child != null) {
                    return child.Name;
                }
            }
 
            // Otherwise, use the system provided name
            if (systemIAccessible != null) {
                string retval = systemIAccessible.get_accName(childID);
 
                if (IsClientObject) {
                    if (retval == null || retval.Length == 0) {
                        retval = Name;  // Name the child after its parent
                    }
                }
 
                return retval;
            }
 
            return null;
        }
 
        /// <include file='doc\AccessibleObject.uex' path='docs/doc[@for="AccessibleObject.IAccessible.accParent"]/*' />
        /// <internalonly/>
        /// <devdoc>
        /// Return the parent object
        /// </devdoc>
        object IAccessible.accParent {
            get {
                IntSecurity.UnmanagedCode.Demand();
 
                Debug.WriteLineIf(CompModSwitches.MSAA.TraceInfo, "AccessibleObject.accParent: this = " + this.ToString());
                AccessibleObject parent = Parent;
                if (parent != null) {
                    // Some debugging related tests
                    //
                    Debug.Assert(parent != this, "An accessible object is returning itself as its own parent. This can cause accessibility clients to hang.");
                    if (parent == this) {
                        parent = null;  // This should prevent accessibility clients from hanging
                    }                    
                }
                
                return AsIAccessible(parent);
            }
        }
 
        /// <include file='doc\AccessibleObject.uex' path='docs/doc[@for="AccessibleObject.IAccessible.get_accRole"]/*' />
        /// <internalonly/>
        /// <devdoc>
        /// <para>
        /// The role property describes an object's purpose in terms of its
        /// relationship with sibling or child objects.
        /// </para>
        /// </devdoc>
        object IAccessible.get_accRole(object childID) {
 
            if (IsClientObject) {
                ValidateChildID(ref childID);
 
                // Return the role property if available
                if (childID.Equals(NativeMethods.CHILDID_SELF)) {
                    return (int)Role;
                }
 
                // If we have an accessible object collection, get the appropriate child
                AccessibleObject child = GetAccessibleChild(childID);
                if (child != null) {
                    return (int)child.Role;
                }
            }
 
            if (systemIAccessible != null) {
                return systemIAccessible.get_accRole(childID);
            }
 
            return null;
        }
 
        /// <include file='doc\AccessibleObject.uex' path='docs/doc[@for="AccessibleObject.IAccessible.accSelection"]/*' />
        /// <internalonly/>
        /// <devdoc>
        /// Return the object or child selection
        /// </devdoc>
        object IAccessible.accSelection { 
            get {
 
                if (IsClientObject) {
                    Debug.WriteLineIf(CompModSwitches.MSAA.TraceInfo, "AccessibleObject.GetAccSelection: this = " + 
                        this.ToString());
        
                    AccessibleObject obj = GetSelected();                
                    if (obj != null) {
                        return AsVariant(obj);
                    }
                }
 
                if (systemIAccessible != null) {
                    try {
                        return systemIAccessible.accSelection;
                    }
                    catch (COMException e) {
                        if (e.ErrorCode != NativeMethods.DISP_E_MEMBERNOTFOUND) {
                            throw e;
                        }
                    }
                }
                
                return null;
            }
        }
 
        /// <include file='doc\AccessibleObject.uex' path='docs/doc[@for="AccessibleObject.IAccessible.get_accState"]/*' />
        /// <internalonly/>
        /// <devdoc>
        /// <para>
        /// Return the object or child state
        /// </para>
        /// </devdoc>
        object IAccessible.get_accState(object childID) {
 
            if (IsClientObject) {
                ValidateChildID(ref childID);
 
                Debug.WriteLineIf(CompModSwitches.MSAA.TraceInfo, "AccessibleObject.GetAccState: this = " + 
                    this.ToString() + ", childID = " + childID.ToString());
 
                // Return the state property if available
                if (childID.Equals(NativeMethods.CHILDID_SELF)) {
                    return (int)State;
                }
 
                // If we have an accessible object collection, get the appropriate child
                AccessibleObject child = GetAccessibleChild(childID);
                if (child != null) {
                    return (int)child.State;
                }
            }
 
            if (systemIAccessible != null) {
                return systemIAccessible.get_accState(childID);
            }
 
            return null;
        }
 
        /// <include file='doc\AccessibleObject.uex' path='docs/doc[@for="AccessibleObject.IAccessible.get_accValue"]/*' />
        /// <internalonly/>
        /// <devdoc>
        /// <para>
        /// Return the object or child value
        /// </para>
        /// </devdoc>
        string IAccessible.get_accValue(object childID) {
 
            IntSecurity.UnmanagedCode.Demand();
 
            if (IsClientObject) {
                ValidateChildID(ref childID);
 
                // Return the value property if available
                if (childID.Equals(NativeMethods.CHILDID_SELF)) {
                    return Value;
                }
 
                // If we have an accessible object collection, get the appropriate child
                AccessibleObject child = GetAccessibleChild(childID);
                if (child != null) {
                    return child.Value;
                }
            }
 
            if (systemIAccessible != null) {
                try {
                    return systemIAccessible.get_accValue(childID);
                }
                catch (COMException e) {
                    if (e.ErrorCode != NativeMethods.DISP_E_MEMBERNOTFOUND) {
                        throw e;
                    }
                }
            }
 
            return null;
        }
        
        /// <include file='doc\AccessibleObject.uex' path='docs/doc[@for="AccessibleObject.IAccessible.set_accName"]/*' />
        /// <internalonly/>
        /// <devdoc>
        /// <para>
        /// Set the object or child name
        /// </para>
        /// </devdoc>
        void IAccessible.set_accName(
                              Object childID,
                              string newName) {
 
            if (IsClientObject) {
                ValidateChildID(ref childID);
 
                // Set the name property if available
                if (childID.Equals(NativeMethods.CHILDID_SELF)) {
                    // Attempt to set the name property
                    Name = newName;
                    return;
                }
 
                // If we have an accessible object collection, get the appropriate child
                AccessibleObject child = GetAccessibleChild(childID);
                if (child != null) {
                    child.Name = newName;
                    return;
                }
            }
 
            if (systemIAccessible != null) {
                systemIAccessible.set_accName(childID, newName);
                return;
            }
        }
 
        /// <include file='doc\AccessibleObject.uex' path='docs/doc[@for="AccessibleObject.IAccessible.set_accValue"]/*' />
        /// <internalonly/>
        /// <devdoc>
        /// <para>
        /// Set the object or child value
        /// </para>
        /// </devdoc>
        void IAccessible.set_accValue(
                               Object childID,
                               string newValue) {
 
            IntSecurity.UnmanagedCode.Demand();
 
            if (IsClientObject) {
                ValidateChildID(ref childID);
 
                // Set the value property if available
                if (childID.Equals(NativeMethods.CHILDID_SELF)) {
                    // Attempt to set the value property
                    Value = newValue;
                    return;
                }
 
                // If we have an accessible object collection, get the appropriate child
                AccessibleObject child = GetAccessibleChild(childID);
                if (child != null) {
                    child.Value = newValue;
                    return;
                }
            }
 
            if (systemIAccessible != null) {
                try {
                    systemIAccessible.set_accValue(childID, newValue);
                }
                catch (COMException e) {
                    if (e.ErrorCode != NativeMethods.DISP_E_MEMBERNOTFOUND) {
                        throw e;
                    }
                }
                return;
            }
        }
        
        /// <include file='doc\AccessibleObject.uex' path='docs/doc[@for="AccessibleObject.UnsafeNativeMethods.IOleWindow.GetWindow"]/*' />
        /// <devdoc>
        ///     [Microsoft - Apr04]
        ///
        ///     Now that AccessibleObject is used to wrap all system-provided (OLEACC.DLL) accessible
        ///     objects, it needs to implement IOleWindow and pass this down to the inner object. This is
        ///     necessary because the OS function WindowFromAccessibleObject() walks up the parent chain
        ///     looking for the first object that implements IOleWindow, and uses that to get the hwnd.
        ///
        ///     But this creates a new problem for AccessibleObjects that do NOT have windows, ie. which
        ///     represent simple elements. To the OS, these simple elements will now appear to implement
        ///     IOleWindow, so it will try to get hwnds from them - which they simply cannot provide.
        ///
        ///     To work around this problem, the AccessibleObject for a simple element will delegate all
        ///     IOleWindow calls up the parent chain itself. This will stop at the first window-based
        ///     accessible object, which will be able to return an hwnd back to the OS. So we are
        ///     effectively 'preempting' what WindowFromAccessibleObject() would do.
        /// </devdoc>
        /// <internalonly/>
        [SecurityPermission(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)]
        int UnsafeNativeMethods.IOleWindow.GetWindow(out IntPtr hwnd) {
            // See if we have an inner object that can provide the window handle
            if (systemIOleWindow != null) {
                return systemIOleWindow.GetWindow(out hwnd);
            }
 
            // Otherwise delegate to the parent object
            AccessibleObject parent = this.Parent;
            if (parent is UnsafeNativeMethods.IOleWindow) {
                return (parent as UnsafeNativeMethods.IOleWindow).GetWindow(out hwnd);
            }
 
            // Or fail if there is no parent
            hwnd = IntPtr.Zero;
            return NativeMethods.E_FAIL;
        }
 
        /// <include file='doc\AccessibleObject.uex' path='docs/doc[@for="AccessibleObject.UnsafeNativeMethods.IOleWindow.ContextSensitiveHelp"]/*' />
        /// <devdoc>
        ///     See GetWindow() above for details.
        /// </devdoc>
        /// <internalonly/>
        [SecurityPermission(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)]
        void UnsafeNativeMethods.IOleWindow.ContextSensitiveHelp(int fEnterMode) {
            // See if we have an inner object that can provide help
            if (systemIOleWindow != null) {
                systemIOleWindow.ContextSensitiveHelp(fEnterMode);
                return;
            }
 
            // Otherwise delegate to the parent object
            AccessibleObject parent = this.Parent;
            if (parent is UnsafeNativeMethods.IOleWindow) {
                (parent as UnsafeNativeMethods.IOleWindow).ContextSensitiveHelp(fEnterMode);
                return;
            }
 
            // Or do nothing if there is no parent
        }
 
        /// <include file='doc\AccessibleObject.uex' path='docs/doc[@for="AccessibleObject.UnsafeNativeMethods.IEnumVariant.Clone"]/*' />
        /// <devdoc>
        ///    <para>
        ///       Clone this accessible object.
        ///    </para>
        /// </devdoc>
        void UnsafeNativeMethods.IEnumVariant.Clone(UnsafeNativeMethods.IEnumVariant[] v) {
            EnumVariant.Clone(v);
        }
        
        /// <include file='doc\AccessibleObject.uex' path='docs/doc[@for="AccessibleObject.UnsafeNativeMethods.IEnumVariant.Next"]/*' />
        /// <devdoc>
        ///    <para>
        ///       Obtain the next n children of this accessible object.
        ///    </para>
        /// </devdoc>
        int UnsafeNativeMethods.IEnumVariant.Next(int n, IntPtr rgvar, int[] ns) {
            return EnumVariant.Next(n, rgvar, ns);
        }
                  
        /// <include file='doc\AccessibleObject.uex' path='docs/doc[@for="AccessibleObject.UnsafeNativeMethods.IEnumVariant.Reset"]/*' />
        /// <devdoc>
        ///      Resets the child accessible object enumerator.
        /// </devdoc>
        void UnsafeNativeMethods.IEnumVariant.Reset() {
            EnumVariant.Reset();
        }
        
        /// <include file='doc\AccessibleObject.uex' path='docs/doc[@for="AccessibleObject.UnsafeNativeMethods.IEnumVariant.Skip"]/*' />
        /// <devdoc>
        ///    <para>
        ///       Skip the next n child accessible objects
        ///    </para>
        /// </devdoc>
        void UnsafeNativeMethods.IEnumVariant.Skip(int n) {
            EnumVariant.Skip(n);
        }
        
        /// <include file='doc\AccessibleObject.uex' path='docs/doc[@for="AccessibleObject.Navigate"]/*' />
        /// <devdoc>
        ///    <para>When overridden in a derived class,
        ///       navigates to another object.</para>
        /// </devdoc>
        [SecurityPermission(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)]
        public virtual AccessibleObject Navigate(AccessibleNavigation navdir) {
        
            // Some default behavior for objects with AccessibleObject children
            //
            if (GetChildCount() >= 0) {
                switch(navdir) {
                    case AccessibleNavigation.FirstChild:
                        return GetChild(0);
                    case AccessibleNavigation.LastChild:
                        return GetChild(GetChildCount() - 1);
                    case AccessibleNavigation.Previous:
                    case AccessibleNavigation.Up:
                    case AccessibleNavigation.Left:
                        if (Parent.GetChildCount() > 0) {
                            return null;
                        }
                        break;
                    case AccessibleNavigation.Next:
                    case AccessibleNavigation.Down:
                    case AccessibleNavigation.Right:
                        if (Parent.GetChildCount() > 0) {
                            return null;
                        }
                        break;
                }
            }
        
            if (systemIAccessible != null) {
                try {
                    object retObject = null;
                    if (!SysNavigate((int)navdir, NativeMethods.CHILDID_SELF, out retObject))
                        retObject = systemIAccessible.accNavigate((int)navdir, NativeMethods.CHILDID_SELF);
                    return WrapIAccessible(retObject);
                }
                catch (COMException e) {
                    if (e.ErrorCode != NativeMethods.DISP_E_MEMBERNOTFOUND) {
                        throw e;
                    }
                }
            }
            return null;
        }
        
        /// <include file='doc\AccessibleObject.uex' path='docs/doc[@for="AccessibleObject.Select"]/*' />
        /// <devdoc>
        ///    <para>
        ///       Selects this accessible object.
        ///    </para>
        /// </devdoc>
        [SecurityPermission(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)]
        public virtual void Select(AccessibleSelection flags) {
        
            // By default, do the system behavior
            //
            if (systemIAccessible != null) {
                try {
                    systemIAccessible.accSelect((int)flags, 0);
                }
                catch (COMException e) {
                    // Not all objects provide the select function
                    //
                    if (e.ErrorCode != NativeMethods.DISP_E_MEMBERNOTFOUND) {
                        throw e;
                    }
                }
                return;
            }
        }
        
        private object AsVariant(AccessibleObject obj) {
            if (obj == this) {
                return NativeMethods.CHILDID_SELF;
            }
            return AsIAccessible(obj);
        }
        
        private IAccessible AsIAccessible(AccessibleObject obj) {
            if (obj != null && obj.systemWrapper) {
                return obj.systemIAccessible;
            }
            return obj;
        }
 
        /// <include file='doc\AccessibleObject.uex' path='docs/doc[@for="AccessibleObject.AccessibleObjectId"]/*' />
        /// <devdoc>
        ///     Indicates what kind of 'inner' system accessible object we are using as our fall-back
        ///     implementation of IAccessible (when the systemIAccessible member is not null). The inner
        ///     object is provided by OLEACC.DLL. Note that although the term 'id' is used, this value
        ///     really represents a category or type of accessible object. Ids are only unique among
        ///     accessible objects associated with the same window handle. Currently supported ids are...
        ///
        ///     OBJID_CLIENT - represents the window's client area (including any child windows)
        ///     OBJID_WINDOW - represents the window's non-client area (including caption, frame controls and scrollbars)
        ///
        ///     NOTE: When the id is OBJID_WINDOW, we short-circuit most of the virtual override behavior of
        ///     AccessibleObject, and turn the object into a simple wrapper around the inner system object. So
        ///     for a *user-defined* accessible object, that has NO inner object, its important that the id is
        ///     left as OBJID_CLIENT, otherwise the object will be short-circuited into a total NOP!
        /// </devdoc>
        /// <internalonly/>
        internal int AccessibleObjectId {
            get {
                return accObjId;
            }
            set {
                accObjId = value;
            }
        }
        
        /// <include file='doc\AccessibleObject.uex' path='docs/doc[@for="AccessibleObject.IsClientObject"]/*' />
        /// <devdoc>
        ///    Indicates whether this accessible object represents the client area of the window.
        /// </devdoc>
        /// <internalonly/>
        internal bool IsClientObject {
            get {
                return AccessibleObjectId == NativeMethods.OBJID_CLIENT;
            }
        }
        
        /// <include file='doc\AccessibleObject.uex' path='docs/doc[@for="AccessibleObject.IsNonClientObject"]/*' />
        /// <devdoc>
        ///    Indicates whether this accessible object represents the non-client area of the window.
        /// </devdoc>
        /// <internalonly/>
        internal bool IsNonClientObject {
            get {
                return AccessibleObjectId == NativeMethods.OBJID_WINDOW;
            }
        }
 
        /// <devdoc>
        /// </devdoc>
        /// <internalonly/>
        [SecurityPermission(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)]
        internal IAccessible GetSystemIAccessibleInternal() {
            return this.systemIAccessible;
        }
 
        /// <include file='doc\AccessibleObject.uex' path='docs/doc[@for="AccessibleObject.UseStdAccessibleObjects"]/*' />
        /// <devdoc>
        ///    <para>[To be supplied.]</para>
        /// </devdoc>
        /// <internalonly/>
        [SecurityPermission(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)]
        protected void UseStdAccessibleObjects(IntPtr handle) {
            UseStdAccessibleObjects(handle, AccessibleObjectId);
        }
        
        /// <include file='doc\AccessibleObject.uex' path='docs/doc[@for="AccessibleObject.UseStdAccessibleObjects1"]/*' />
        /// <internalonly/>
        [SecurityPermission(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)]
        protected void UseStdAccessibleObjects(IntPtr handle, int objid) {
            // Get a standard accessible Object
            Guid IID_IAccessible = new Guid(NativeMethods.uuid_IAccessible);
            object acc = null;
            int result = UnsafeNativeMethods.CreateStdAccessibleObject(
                                                          new HandleRef(this, handle),
                                                          objid,
                                                          ref IID_IAccessible,
                                                          ref acc);
 
            // Get the IEnumVariant interface
            Guid IID_IEnumVariant = new Guid(NativeMethods.uuid_IEnumVariant);
            object en = null;
            result = UnsafeNativeMethods.CreateStdAccessibleObject(
                                                      new HandleRef(this, handle),
                                                      objid,
                                                      ref IID_IEnumVariant,
                                                      ref en);
 
            Debug.Assert(acc != null, "SystemIAccessible is null");
            Debug.Assert(en != null, "SystemIEnumVariant is null");
 
            if (acc != null || en != null) {
                systemIAccessible = (IAccessible)acc;
                systemIEnumVariant = (UnsafeNativeMethods.IEnumVariant)en;
                systemIOleWindow = acc as UnsafeNativeMethods.IOleWindow;
            }
        }
 
        /// <devdoc>
        ///     Performs custom navigation between parent/child/sibling accessible objects. This is basically
        ///     just a wrapper for GetSysChild(), that does some of the dirty work, such as wrapping the
        ///     returned object in a VARIANT. Usage is similar to GetSysChild(). Called prior to calling
        ///     IAccessible.accNavigate on the 'inner' system accessible object.
        /// </devdoc>
        /// <internalonly/>
        private bool SysNavigate(int navDir, Object childID, out Object retObject) {
            retObject = null;
 
            // Only override system navigation relative to ourselves (since we can't interpret OLEACC child ids)
            if (!childID.Equals(NativeMethods.CHILDID_SELF))
                return false;
 
            // Perform any supported navigation operation (fall back on system for unsupported navigation ops)
            AccessibleObject newObject;
            if (!GetSysChild((AccessibleNavigation) navDir, out newObject))
                return false;
 
            // If object found, wrap in a VARIANT. Otherwise return null for 'end of list' (OLEACC expects this)
            retObject = (newObject == null) ? null : AsVariant(newObject);
 
            // Tell caller not to fall back on system behavior now
            return true;
        }
 
        /// <include file='doc\AccessibleObject.uex' path='docs/doc[@for="AccessibleObject.ValidateChildID"]/*' />
        /// <devdoc>
        ///      Make sure that the childID is valid.
        /// </devdoc>
        internal void ValidateChildID(ref object childID) {
            // An empty childID is considered to be the same as CHILDID_SELF.
            // Some accessibility programs pass null into our functions, so we
            // need to convert them here.
            if (childID == null) {
                childID = NativeMethods.CHILDID_SELF;
            }
            else if (childID.Equals(NativeMethods.DISP_E_PARAMNOTFOUND)) {
                childID = 0;
            }
            else if (!(childID is Int32)) {
                // AccExplorer seems to occasionally pass in objects instead of an int ChildID.
                //
                childID = 0;
            }
        }
 
        private AccessibleObject WrapIAccessible(object iacc) {
            IAccessible accessible = iacc as IAccessible;
            if (accessible == null) {
                return null;
            }
        
            // Check to see if this object already wraps iacc
            //
            if (this.systemIAccessible == iacc) {
                return this;
            }
        
            return new AccessibleObject(accessible);
        }                             
 
        /// <include file='doc\AccessibleObject.uex' path='docs/doc[@for="IReflect.GetMethod"]/*' />
        /// <internalonly/>
        /// <devdoc>
        /// Return the requested method if it is implemented by the Reflection object.  The
        /// match is based upon the name and DescriptorInfo which describes the signature
        /// of the method. 
        /// </devdoc>
        MethodInfo IReflect.GetMethod(string name, BindingFlags bindingAttr, Binder binder, Type[] types, ParameterModifier[] modifiers) {
            return typeof(IAccessible).GetMethod(name, bindingAttr, binder, types, modifiers);
        }
        
        /// <include file='doc\AccessibleObject.uex' path='docs/doc[@for="IReflect.GetMethod1"]/*' />
        /// <internalonly/>
        /// <devdoc>
        /// Return the requested method if it is implemented by the Reflection object.  The
        /// match is based upon the name of the method.  If the object implementes multiple methods
        /// with the same name an AmbiguousMatchException is thrown.
        /// </devdoc>
        MethodInfo IReflect.GetMethod(string name, BindingFlags bindingAttr) {
            return typeof(IAccessible).GetMethod(name, bindingAttr);
        }
        
        /// <include file='doc\AccessibleObject.uex' path='docs/doc[@for="IReflect.GetMethods"]/*' />
        /// <internalonly/>
        MethodInfo[] IReflect.GetMethods(BindingFlags bindingAttr) {
            return typeof(IAccessible).GetMethods(bindingAttr);
        }
        
        /// <include file='doc\AccessibleObject.uex' path='docs/doc[@for="IReflect.GetField"]/*' />
        /// <internalonly/>
        /// <devdoc>
        /// Return the requestion field if it is implemented by the Reflection object.  The
        /// match is based upon a name.  There cannot be more than a single field with
        /// a name.
        /// </devdoc>
        FieldInfo IReflect.GetField(string name, BindingFlags bindingAttr) {
            return typeof(IAccessible).GetField(name, bindingAttr);
        }
        
        /// <include file='doc\AccessibleObject.uex' path='docs/doc[@for="IReflect.GetFields"]/*' />
        /// <internalonly/>
        FieldInfo[] IReflect.GetFields(BindingFlags bindingAttr) {
            return typeof(IAccessible).GetFields(bindingAttr);
        }
        
        /// <include file='doc\AccessibleObject.uex' path='docs/doc[@for="IReflect.GetProperty"]/*' />
        /// <internalonly/>
        /// <devdoc>
        /// Return the property based upon name.  If more than one property has the given
        /// name an AmbiguousMatchException will be thrown.  Returns null if no property
        /// is found.
        /// </devdoc>
        PropertyInfo IReflect.GetProperty(string name, BindingFlags bindingAttr) {
            return typeof(IAccessible).GetProperty(name, bindingAttr);
        }
        
        /// <include file='doc\AccessibleObject.uex' path='docs/doc[@for="IReflect.GetProperty1"]/*' />
        /// <internalonly/>
        /// <devdoc>
        /// Return the property based upon the name and Descriptor info describing the property
        /// indexing.  Return null if no property is found.
        /// </devdoc>
        PropertyInfo IReflect.GetProperty(string name, BindingFlags bindingAttr, Binder binder, Type returnType, Type[] types, ParameterModifier[] modifiers) {
            return typeof(IAccessible).GetProperty(name, bindingAttr, binder, returnType, types, modifiers);
        }
        
        /// <include file='doc\AccessibleObject.uex' path='docs/doc[@for="IReflect.GetProperties"]/*' />
        /// <internalonly/>
        /// <devdoc>
        /// Returns an array of PropertyInfos for all the properties defined on 
        /// the Reflection object.
        /// </devdoc>
        PropertyInfo[] IReflect.GetProperties(BindingFlags bindingAttr) {
            return typeof(IAccessible).GetProperties(bindingAttr);
        }
        
        /// <include file='doc\AccessibleObject.uex' path='docs/doc[@for="IReflect.GetMember"]/*' />
        /// <internalonly/>
        /// <devdoc>
        /// Return an array of members which match the passed in name.
        /// </devdoc>
        MemberInfo[] IReflect.GetMember(string name, BindingFlags bindingAttr) {
            return typeof(IAccessible).GetMember(name, bindingAttr);
        }
        
        /// <include file='doc\AccessibleObject.uex' path='docs/doc[@for="IReflect.GetMembers"]/*' />
        /// <internalonly/>
        /// <devdoc>
        /// Return an array of all of the members defined for this object.
        /// </devdoc>
        MemberInfo[] IReflect.GetMembers(BindingFlags bindingAttr) {
            return typeof(IAccessible).GetMembers(bindingAttr);
        }
        
        /// <include file='doc\AccessibleObject.uex' path='docs/doc[@for="IReflect.InvokeMember"]/*' />
        /// <internalonly/>
        /// <devdoc>
        /// Description of the Binding Process.
        /// We must invoke a method that is accessable and for which the provided
        /// parameters have the most specific match.  A method may be called if
        /// 1. The number of parameters in the method declaration equals the number of 
        /// arguments provided to the invocation
        /// 2. The type of each argument can be converted by the binder to the
        /// type of the type of the parameter.
        ///
        /// The binder will find all of the matching methods.  These method are found based
        /// upon the type of binding requested (MethodInvoke, Get/Set Properties).  The set
        /// of methods is filtered by the name, number of arguments and a set of search modifiers
        /// defined in the Binder.
        ///
        /// After the method is selected, it will be invoked.  Accessability is checked
        /// at that point.  The search may be control which set of methods are searched based
        /// upon the accessibility attribute associated with the method.
        ///
        /// The BindToMethod method is responsible for selecting the method to be invoked.
        /// For the default binder, the most specific method will be selected.
        ///
        /// This will invoke a specific member...
        /// @exception If <var>invokeAttr</var> is CreateInstance then all other
        /// Access types must be undefined.  If not we throw an ArgumentException.
        /// @exception If the <var>invokeAttr</var> is not CreateInstance then an
        /// ArgumentException when <var>name</var> is null.
        /// @exception ArgumentException when <var>invokeAttr</var> does not specify the type
        /// @exception ArgumentException when <var>invokeAttr</var> specifies both get and set of
        /// a property or field.
        /// @exception ArgumentException when <var>invokeAttr</var> specifies property set and
        /// invoke method.
        /// </devdoc>
        object IReflect.InvokeMember(string name, BindingFlags invokeAttr, Binder binder, object target, object[] args, ParameterModifier[] modifiers, CultureInfo culture, string[] namedParameters) {
            
            if (args.Length == 0) {
                MemberInfo[] member = typeof(IAccessible).GetMember(name);
                if (member != null && member.Length > 0 && member[0] is PropertyInfo) {
                    MethodInfo getMethod = ((PropertyInfo)member[0]).GetGetMethod();
                    if (getMethod != null && getMethod.GetParameters().Length > 0) {
                        args = new object[getMethod.GetParameters().Length];
                        for (int i = 0; i < args.Length; i++) {
                            args[i] = NativeMethods.CHILDID_SELF;    
                        }
                    }
                }
            }
            return typeof(IAccessible).InvokeMember(name, invokeAttr, binder, target, args, modifiers, culture, namedParameters);
        }
        
        /// <include file='doc\AccessibleObject.uex' path='docs/doc[@for="IReflect.UnderlyingSystemType"]/*' />
        /// <internalonly/>
        /// <devdoc>
        /// Return the underlying Type that represents the IReflect Object.  For expando object,
        /// this is the (Object) IReflectInstance.GetType().  For Type object it is this.
        /// </devdoc>
        Type IReflect.UnderlyingSystemType {
            get {
                return typeof(IAccessible);
            }
        }
 
        UnsafeNativeMethods.IRawElementProviderSimple UnsafeNativeMethods.IRawElementProviderHwndOverride.GetOverrideProviderForHwnd(IntPtr hwnd) {
            return GetOverrideProviderForHwnd(hwnd);
        }
 
        bool UnsafeNativeMethods.IRangeValueProvider.IsReadOnly {
            get {
                return IsReadOnly;
            }
        }
 
        double UnsafeNativeMethods.IRangeValueProvider.LargeChange {
            get {
                return LargeChange;
            }
        }
 
        double UnsafeNativeMethods.IRangeValueProvider.Maximum {
            get {
                return Maximum;
            }
        }
 
        double UnsafeNativeMethods.IRangeValueProvider.Minimum {
            get {
                return Minimum;
            }
        }
 
        double UnsafeNativeMethods.IRangeValueProvider.SmallChange {
            get {
                return SmallChange;
            }
        }
 
        double UnsafeNativeMethods.IRangeValueProvider.Value {
            get {
                return RangeValue;
            }
        }
 
        void UnsafeNativeMethods.IRangeValueProvider.SetValue(double value) {
            SetValue(value);
        }
 
        object[] UnsafeNativeMethods.ISelectionProvider.GetSelection() {
            return GetSelection();
        }
 
        bool UnsafeNativeMethods.ISelectionProvider.CanSelectMultiple {
            get {
                return CanSelectMultiple;
            }
        }
 
        bool UnsafeNativeMethods.ISelectionProvider.IsSelectionRequired {
            get {
                return IsSelectionRequired;
            }
        }
 
        void UnsafeNativeMethods.ISelectionItemProvider.Select() {
            SelectItem();
        }
 
        void UnsafeNativeMethods.ISelectionItemProvider.AddToSelection() {
            AddToSelection();
        }
 
        void UnsafeNativeMethods.ISelectionItemProvider.RemoveFromSelection() {
            RemoveFromSelection();
        }
 
        bool UnsafeNativeMethods.ISelectionItemProvider.IsSelected {
            get {
                return IsItemSelected;
            }
        }
 
        UnsafeNativeMethods.IRawElementProviderSimple UnsafeNativeMethods.ISelectionItemProvider.SelectionContainer {
            get {
                return ItemSelectionContainer;
            }
        }
 
        /// <summary>
        /// Raises the UIA Notification event.
        /// The event is available starting with Windows 10, version 1709.
        /// </summary>
        /// <param name="notificationKind">The type of notification</param>
        /// <param name="notificationProcessing">Indicates how to process notifications</param>
        /// <param name="notificationText">Notification text</param>
        /// <returns>
        /// True if operation succeeds.
        /// False if the underlying windows infrastructure is not available or the operation had failed.
        /// Use Marshal.GetLastWin32Error for details.
        /// </returns>
        public bool RaiseAutomationNotification(
            AutomationNotificationKind notificationKind,
            AutomationNotificationProcessing notificationProcessing,
            string notificationText) {
 
            if (!AccessibilityImprovements.Level3 || !notificationEventAvailable) {
                return false;
            }
 
            int result = NativeMethods.S_FALSE;
            try {
                // The activityId can be any string. It cannot be null. It isn�t used currently.
                result = UnsafeNativeMethods.UiaRaiseNotificationEvent(
                    this,
                    notificationKind,
                    notificationProcessing,
                    notificationText,
                    String.Empty);
            }
            catch (EntryPointNotFoundException) {
                // The UIA Notification event is not available, so don't attempt to raise it again.
                notificationEventAvailable = false;
            }
 
            return result == NativeMethods.S_OK;
        }
 
        /// <summary>
        /// Raises the LiveRegionChanged UIA event.
        /// This method must be overridden in derived classes that support the UIA live region feature.
        /// </summary>
        /// <returns>True if operation succeeds, False otherwise.</returns>
        public virtual bool RaiseLiveRegionChanged() {
            throw new NotSupportedException(SR.GetString(SR.AccessibleObjectLiveRegionNotSupported));
        }
 
        internal bool RaiseAutomationEvent(int eventId) {
            if (UnsafeNativeMethods.UiaClientsAreListening()) {
                int result = UnsafeNativeMethods.UiaRaiseAutomationEvent(this, eventId);
                return result == NativeMethods.S_OK;
            }
 
            return false;
        }
 
        internal bool RaiseAutomationPropertyChangedEvent(int propertyId, object oldValue, object newValue) {
            if (UnsafeNativeMethods.UiaClientsAreListening()) {
                int result = UnsafeNativeMethods.UiaRaiseAutomationPropertyChangedEvent(this, propertyId, oldValue, newValue);
                return result == NativeMethods.S_OK;
            }
 
            return false;
        }
 
        internal bool RaiseStructureChangedEvent(UnsafeNativeMethods.StructureChangeType structureChangeType, int[] runtimeId) {
            if (UnsafeNativeMethods.UiaClientsAreListening()) {
                int result = UnsafeNativeMethods.UiaRaiseStructureChangedEvent(this, structureChangeType, runtimeId, runtimeId == null ? 0 : runtimeId.Length);
                return result == NativeMethods.S_OK;
            }
 
            return false;
        }
 
        #region IScrollItemProvider implementation
 
        void UnsafeNativeMethods.IScrollItemProvider.ScrollIntoView() {
            ScrollIntoView();
        }
 
        internal virtual void ScrollIntoView() {
            Debug.Fail($"{nameof(this.ScrollIntoView)}() is not overriden");
        }
 
        #endregion
 
        private class EnumVariantObject : UnsafeNativeMethods.IEnumVariant {
        
            private int currentChild = 0;
            private AccessibleObject owner;
            
            public EnumVariantObject(AccessibleObject owner) {
                Debug.Assert(owner != null, "Cannot create EnumVariantObject with a null owner");
                this.owner = owner;
            }
            
            public EnumVariantObject(AccessibleObject owner, int currentChild) {
                Debug.Assert(owner != null, "Cannot create EnumVariantObject with a null owner");
                this.owner = owner;
                this.currentChild = currentChild;
            }
 
            void UnsafeNativeMethods.IEnumVariant.Clone(UnsafeNativeMethods.IEnumVariant[] v) {
                v[0] = new EnumVariantObject(owner, currentChild);
            }
 
            /// <include file='doc\AccessibleObject.uex' path='docs/doc[@for="AccessibleObject.EnumVariantObject.UnsafeNativeMethods.IEnumVariant.Reset"]/*' />
            /// <devdoc>
            ///     Resets the child accessible object enumerator.
            /// </devdoc>
            void UnsafeNativeMethods.IEnumVariant.Reset() {
                currentChild = 0;
    
                // SECREVIEW: This assert is safe, and is needed to fix VSWhidbey#126319
                // (allow access to children of an AccessibleObject in partial trust).
                //
                IntSecurity.UnmanagedCode.Assert();
                try {
                    if (owner.systemIEnumVariant != null)
                        owner.systemIEnumVariant.Reset();
                }
                finally {
                    CodeAccessPermission.RevertAssert();
                }
            }
            
            /// <include file='doc\AccessibleObject.uex' path='docs/doc[@for="AccessibleObject.EnumVariantObject.UnsafeNativeMethods.IEnumVariant.Skip"]/*' />
            /// <devdoc>
            ///     Skips the next n child accessible objects.
            /// </devdoc>
            void UnsafeNativeMethods.IEnumVariant.Skip(int n) {
                currentChild += n;
 
                // SECREVIEW: This assert is safe, and is needed to fix VSWhidbey#126319
                // (allow access to children of an AccessibleObject in partial trust).
                //
                IntSecurity.UnmanagedCode.Assert();
                try {
                    if (owner.systemIEnumVariant != null)
                        owner.systemIEnumVariant.Skip(n);
                }
                finally {
                    CodeAccessPermission.RevertAssert();
                }
            }    
 
            /// <include file='doc\AccessibleObject.uex' path='docs/doc[@for="AccessibleObject.EnumVariantObject.UnsafeNativeMethods.IEnumVariant.Next"]/*' />
            /// <devdoc>
            ///     Gets the next n child accessible objects.
            /// </devdoc>
            int UnsafeNativeMethods.IEnumVariant.Next(int n, IntPtr rgvar, int[] ns) {
                // NOTE: rgvar is a pointer to an array of variants
 
                if (owner.IsClientObject) {
                    Debug.WriteLineIf(CompModSwitches.MSAA.TraceInfo, "EnumVariantObject: owner = " + owner.ToString() + ", n = " + n);
 
                    Debug.Indent();
                    
                    int childCount;
                    int[] newOrder;
                   
                    if ((childCount = owner.GetChildCount()) >= 0)
                        NextFromChildCollection(n, rgvar, ns, childCount);
                    else if (owner.systemIEnumVariant == null)
                        NextEmpty(n, rgvar, ns);
                    else if ((newOrder = owner.GetSysChildOrder()) != null)
                        NextFromSystemReordered(n, rgvar, ns, newOrder);
                    else
                        NextFromSystem(n, rgvar, ns);
 
                    Debug.Unindent();
                }
                else {
                    NextFromSystem(n, rgvar, ns);
                }
 
                // Tell caller whether requested number of items was returned. Once list of items has
                // been exhausted, we return S_FALSE so that caller knows to stop calling this method.
                return (ns[0] == n) ? NativeMethods.S_OK : NativeMethods.S_FALSE;
            }
 
            /// <devdoc>
            ///     When we have the IEnumVariant of an accessible proxy provided by the system (ie.
            ///     OLEACC.DLL), we can fall back on that to return the children. Generally, the system
            ///     proxy will enumerate the child windows, create a suitable kind of child accessible
            ///     proxy for each one, and return a set of IDispatch interfaces to these proxy objects.
            /// </devdoc>
            private void NextFromSystem(int n, IntPtr rgvar, int[] ns) {
 
                // SECREVIEW: This assert is safe, and is needed to fix VSWhidbey#126319
                // (allow access to children of an AccessibleObject in partial trust).
                //
                IntSecurity.UnmanagedCode.Assert();
                try {
                    owner.systemIEnumVariant.Next(n, rgvar, ns);
                }
                finally {
                    CodeAccessPermission.RevertAssert();
                }
 
                currentChild += ns[0];
                Debug.WriteLineIf(CompModSwitches.MSAA.TraceInfo, "AccessibleObject.IEV.Next: Delegating to systemIEnumVariant");
            }
 
            /// <devdoc>
            ///     Sometimes we want to rely on the system-provided behavior to create and return child
            ///     accessible objects, but we want to impose a new order on those objects (or even filter
            ///     some objects out).
            ///
            ///     This method takes an array of ints that dictates the new order. It queries the system
            ///     for each child individually, and inserts the result into the correct *new* position.
            ///
            ///     Note: This code has to make certain *assumptions* about OLEACC.DLL proxy object behavior.
            ///     However, this behavior is well documented. We *assume* the proxy will return a set of
            ///     child accessible objects that correspond 1:1 with the owning control's child windows,
            ///     and that the default order it returns these objects in is z-order (which also happens
            ///     to be the order that children appear in the Control.Controls[] collection).
            /// </devdoc>
            private void NextFromSystemReordered(int n, IntPtr rgvar, int[] ns, int[] newOrder) {
                int i;
 
                for (i = 0; i < n && currentChild < newOrder.Length; ++i) {
                    if (!GotoItem(owner.systemIEnumVariant, newOrder[currentChild], GetAddressOfVariantAtIndex(rgvar, i)))
                        break;
                    ++currentChild;
                    Debug.WriteLineIf(CompModSwitches.MSAA.TraceInfo, "AccessibleObject.IEV.Next: adding sys child " + currentChild + " of " + newOrder.Length);
                }
 
                ns[0] = i;
            }
 
            /// <devdoc>
            ///     If we have our own custom accessible child collection, return a set of 1-based integer
            ///     child ids, that the caller will eventually pass back to us via IAccessible.get_accChild().
            /// </devdoc>
            private void NextFromChildCollection(int n, IntPtr rgvar, int[] ns, int childCount) {
                int i;
 
                for (i = 0; i < n && currentChild < childCount; ++i) {
                    ++currentChild;
                    Marshal.GetNativeVariantForObject(((object) currentChild), GetAddressOfVariantAtIndex(rgvar, i));
                    Debug.WriteLineIf(CompModSwitches.MSAA.TraceInfo, "AccessibleObject.IEV.Next: adding own child " + currentChild + " of " + childCount);
                }
 
                ns[0] = i;
            }
 
            /// <devdoc>
            ///     Default behavior if there is no custom child collection or system-provided
            ///     proxy to fall back on. In this case, we return an empty child collection.
            /// </devdoc>
            private void NextEmpty(int n, IntPtr rgvar, int[] ns) {
                ns[0] = 0;
                Debug.WriteLineIf(CompModSwitches.MSAA.TraceInfo, "AccessibleObject.IEV.Next: no children to add");
            }
 
            /// <devdoc>
            ///     Given an IEnumVariant interface, this method jumps to a specific
            ///     item in the collection and extracts the result for that one item.
            /// </devdoc>
            private static bool GotoItem(UnsafeNativeMethods.IEnumVariant iev, int index, IntPtr variantPtr) {
                int[] ns = new int[1];
 
                // SECREVIEW: This assert is safe, and is needed to fix VSWhidbey#126319
                // (allow access to children of an AccessibleObject in partial trust).
                //
                IntSecurity.UnmanagedCode.Assert();
                try {
                    iev.Reset();
                    iev.Skip(index);
                    iev.Next(1, variantPtr, ns);
                }
                finally {
                    CodeAccessPermission.RevertAssert();
                }
 
                return (ns[0] == 1);
            }
 
            /// <devdoc>
            ///     Given an array of pointers to variants, calculate address of a given array element.
            /// </devdoc>
            private static IntPtr GetAddressOfVariantAtIndex(IntPtr variantArrayPtr, int index) {
                int variantSize = 8 + (IntPtr.Size * 2);
                return (IntPtr) ((ulong) variantArrayPtr + ((ulong) index) * ((ulong) variantSize));
            }
            
        }
 
    } // end class AccessibleObject
 
    /// <Summary>
    ///    Internal object passed out to OLEACC clients via WM_GETOBJECT.
    ///    NOTE: THIS CLASS IS INTERNAL FOR SECURITY REASONS AND SHOULD REMAIN SO!
    /// </Summary>
    internal sealed class InternalAccessibleObject : StandardOleMarshalObject, 
                                    UnsafeNativeMethods.IAccessibleInternal,
                                    System.Reflection.IReflect,
                                    UnsafeNativeMethods.IServiceProvider,
                                    UnsafeNativeMethods.IAccessibleEx,
                                    UnsafeNativeMethods.IRawElementProviderSimple,
                                    UnsafeNativeMethods.IRawElementProviderFragment,
                                    UnsafeNativeMethods.IRawElementProviderFragmentRoot,
                                    UnsafeNativeMethods.IInvokeProvider,
                                    UnsafeNativeMethods.IValueProvider,
                                    UnsafeNativeMethods.IRangeValueProvider,
                                    UnsafeNativeMethods.IExpandCollapseProvider,
                                    UnsafeNativeMethods.IToggleProvider,
                                    UnsafeNativeMethods.ITableProvider,
                                    UnsafeNativeMethods.ITableItemProvider,
                                    UnsafeNativeMethods.IGridProvider,
                                    UnsafeNativeMethods.IGridItemProvider,
                                    UnsafeNativeMethods.IEnumVariant,
                                    UnsafeNativeMethods.IOleWindow,
                                    UnsafeNativeMethods.ILegacyIAccessibleProvider,
                                    UnsafeNativeMethods.ISelectionProvider,
                                    UnsafeNativeMethods.ISelectionItemProvider,
                                    UnsafeNativeMethods.IRawElementProviderHwndOverride {
 
        private IAccessible publicIAccessible;                       // AccessibleObject as IAccessible
        private UnsafeNativeMethods.IEnumVariant publicIEnumVariant; // AccessibleObject as IEnumVariant
        private UnsafeNativeMethods.IOleWindow publicIOleWindow;     // AccessibleObject as IOleWindow
        private IReflect publicIReflect;                             // AccessibleObject as IReflect
 
        private UnsafeNativeMethods.IServiceProvider publicIServiceProvider;             // AccessibleObject as IServiceProvider
        private UnsafeNativeMethods.IAccessibleEx publicIAccessibleEx;                   // AccessibleObject as IAccessibleEx
 
        // UIAutomation
        private UnsafeNativeMethods.IRawElementProviderSimple publicIRawElementProviderSimple;    // AccessibleObject as IRawElementProviderSimple
        private UnsafeNativeMethods.IRawElementProviderFragment publicIRawElementProviderFragment;// AccessibleObject as IRawElementProviderFragment
        private UnsafeNativeMethods.IRawElementProviderFragmentRoot publicIRawElementProviderFragmentRoot;// AccessibleObject as IRawElementProviderFragmentRoot
        private UnsafeNativeMethods.IInvokeProvider publicIInvokeProvider;                        // AccessibleObject as IInvokeProvider
        private UnsafeNativeMethods.IValueProvider publicIValueProvider;                          // AccessibleObject as IValueProvider
        private UnsafeNativeMethods.IRangeValueProvider publicIRangeValueProvider;                // AccessibleObject as IRangeValueProvider
        private UnsafeNativeMethods.IExpandCollapseProvider publicIExpandCollapseProvider;        // AccessibleObject as IExpandCollapseProvider
        private UnsafeNativeMethods.IToggleProvider publicIToggleProvider;                        // AccessibleObject as IToggleProvider
        private UnsafeNativeMethods.ITableProvider publicITableProvider;                          // AccessibleObject as ITableProvider
        private UnsafeNativeMethods.ITableItemProvider publicITableItemProvider;                  // AccessibleObject as ITableItemProvider
        private UnsafeNativeMethods.IGridProvider publicIGridProvider;                            // AccessibleObject as IGridProvider
        private UnsafeNativeMethods.IGridItemProvider publicIGridItemProvider;                    // AccessibleObject as IGridItemProvider
        private UnsafeNativeMethods.ILegacyIAccessibleProvider publicILegacyIAccessibleProvider;  // AccessibleObject as ILegayAccessibleProvider
        private UnsafeNativeMethods.ISelectionProvider publicISelectionProvider;                  // AccessibleObject as ISelectionProvider
        private UnsafeNativeMethods.ISelectionItemProvider publicISelectionItemProvider;          // AccessibleObject as ISelectionItemProvider
        private UnsafeNativeMethods.IRawElementProviderHwndOverride publicIRawElementProviderHwndOverride; // AccessibleObject as IRawElementProviderHwndOverride
 
        /// <summary>
        ///     Create a new wrapper. Protect this with UnmanagedCode Permission
        /// </summary>
        [
        SecurityPermission(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)
        ]
        internal InternalAccessibleObject(AccessibleObject accessibleImplemention) {
            // Get all the casts done here to catch any issues early 
            publicIAccessible = (IAccessible) accessibleImplemention;
            publicIEnumVariant = (UnsafeNativeMethods.IEnumVariant) accessibleImplemention;
            publicIOleWindow = (UnsafeNativeMethods.IOleWindow) accessibleImplemention;
            publicIReflect = (IReflect) accessibleImplemention;
            publicIServiceProvider = (UnsafeNativeMethods.IServiceProvider) accessibleImplemention;
            publicIAccessibleEx = (UnsafeNativeMethods.IAccessibleEx) accessibleImplemention;
            publicIRawElementProviderSimple = (UnsafeNativeMethods.IRawElementProviderSimple) accessibleImplemention;
            publicIRawElementProviderFragment = (UnsafeNativeMethods.IRawElementProviderFragment)accessibleImplemention;
            publicIRawElementProviderFragmentRoot = (UnsafeNativeMethods.IRawElementProviderFragmentRoot)accessibleImplemention;
            publicIInvokeProvider = (UnsafeNativeMethods.IInvokeProvider)accessibleImplemention;
            publicIValueProvider = (UnsafeNativeMethods.IValueProvider) accessibleImplemention;
            publicIRangeValueProvider = (UnsafeNativeMethods.IRangeValueProvider)accessibleImplemention;
            publicIExpandCollapseProvider = (UnsafeNativeMethods.IExpandCollapseProvider) accessibleImplemention;
            publicIToggleProvider = (UnsafeNativeMethods.IToggleProvider)accessibleImplemention;
            publicITableProvider = (UnsafeNativeMethods.ITableProvider)accessibleImplemention;
            publicITableItemProvider = (UnsafeNativeMethods.ITableItemProvider)accessibleImplemention;
            publicIGridProvider = (UnsafeNativeMethods.IGridProvider)accessibleImplemention;
            publicIGridItemProvider = (UnsafeNativeMethods.IGridItemProvider)accessibleImplemention;
            publicILegacyIAccessibleProvider = (UnsafeNativeMethods.ILegacyIAccessibleProvider)accessibleImplemention;
            publicISelectionProvider = (UnsafeNativeMethods.ISelectionProvider)accessibleImplemention;
            publicISelectionItemProvider = (UnsafeNativeMethods.ISelectionItemProvider)accessibleImplemention;
            publicIRawElementProviderHwndOverride = (UnsafeNativeMethods.IRawElementProviderHwndOverride)accessibleImplemention;
            // Note: Deliberately not holding onto AccessibleObject to enforce all access through the interfaces
        }
 
        /// <summary>
        ///     If the given object is an AccessibleObject return it as a InternalAccessibleObject
        ///     This ensures we wrap all AccessibleObjects before handing them out to OLEACC
        /// </summary>
        private object AsNativeAccessible(object accObject) {
            if (accObject is AccessibleObject) {
                return new InternalAccessibleObject(accObject as AccessibleObject);
            }
            else {
                return accObject;
            }
        }
 
        /// <summary>
        ///     Wraps AccessibleObject elements of a given array into InternalAccessibleObjects
        /// </summary>
        private object[] AsArrayOfNativeAccessibles(object[] accObjectArray) {
            if (accObjectArray != null && accObjectArray.Length > 0) {
                for (int i = 0; i < accObjectArray.Length; i++) {
                    accObjectArray[i] = AsNativeAccessible(accObjectArray[i]);
                }
            }
            return accObjectArray;
        }
 
        //
        // IAccessibleInternal implementation...
        //
 
        void UnsafeNativeMethods.IAccessibleInternal.accDoDefaultAction(object childID) {
            IntSecurity.UnmanagedCode.Assert();
            publicIAccessible.accDoDefaultAction(childID);
        }
        
        object UnsafeNativeMethods.IAccessibleInternal.accHitTest(int xLeft, int yTop) {
            IntSecurity.UnmanagedCode.Assert();
            return AsNativeAccessible(publicIAccessible.accHitTest(xLeft, yTop));
        }
 
        void UnsafeNativeMethods.IAccessibleInternal.accLocation(out int l, out int t, out int w, out int h, Object childID) {
            IntSecurity.UnmanagedCode.Assert();
            publicIAccessible.accLocation(out l, out t, out w, out h, childID);
        }
 
        object UnsafeNativeMethods.IAccessibleInternal.accNavigate(int navDir, object childID) {
            IntSecurity.UnmanagedCode.Assert();
            return AsNativeAccessible(publicIAccessible.accNavigate(navDir, childID));
        }
 
        void UnsafeNativeMethods.IAccessibleInternal.accSelect(int flagsSelect, Object childID) {
            IntSecurity.UnmanagedCode.Assert();
            publicIAccessible.accSelect(flagsSelect, childID);
        }
 
        object UnsafeNativeMethods.IAccessibleInternal.get_accChild(object childID) {
            IntSecurity.UnmanagedCode.Assert();
            return AsNativeAccessible(publicIAccessible.get_accChild(childID));
        }
 
        int UnsafeNativeMethods.IAccessibleInternal.get_accChildCount() {
            IntSecurity.UnmanagedCode.Assert();
            return publicIAccessible.accChildCount;
        }
 
        string UnsafeNativeMethods.IAccessibleInternal.get_accDefaultAction(Object childID) {
            IntSecurity.UnmanagedCode.Assert();
            return publicIAccessible.get_accDefaultAction(childID);
        }
 
        string UnsafeNativeMethods.IAccessibleInternal.get_accDescription(Object childID) {
            IntSecurity.UnmanagedCode.Assert();
            return publicIAccessible.get_accDescription(childID);
        }
 
        object UnsafeNativeMethods.IAccessibleInternal.get_accFocus() {
            IntSecurity.UnmanagedCode.Assert();
            return AsNativeAccessible(publicIAccessible.accFocus);
        }
 
        string UnsafeNativeMethods.IAccessibleInternal.get_accHelp(Object childID) {
            IntSecurity.UnmanagedCode.Assert();
            return publicIAccessible.get_accHelp(childID);
        }
 
        int UnsafeNativeMethods.IAccessibleInternal.get_accHelpTopic(out string pszHelpFile, Object childID) {
            IntSecurity.UnmanagedCode.Assert();
            return publicIAccessible.get_accHelpTopic(out pszHelpFile, childID);
        }
 
        string UnsafeNativeMethods.IAccessibleInternal.get_accKeyboardShortcut(Object childID) {
            IntSecurity.UnmanagedCode.Assert();
            return publicIAccessible.get_accKeyboardShortcut(childID);
        }
 
        string UnsafeNativeMethods.IAccessibleInternal.get_accName(Object childID) {
            IntSecurity.UnmanagedCode.Assert();
            return publicIAccessible.get_accName(childID);
        }
 
        object UnsafeNativeMethods.IAccessibleInternal.get_accParent() {
            IntSecurity.UnmanagedCode.Assert();
            return AsNativeAccessible(publicIAccessible.accParent);
        }
 
        object UnsafeNativeMethods.IAccessibleInternal.get_accRole(object childID) {
		    IntSecurity.UnmanagedCode.Assert();
		    return publicIAccessible.get_accRole(childID);
	    }
 
        object UnsafeNativeMethods.IAccessibleInternal.get_accSelection() {
            IntSecurity.UnmanagedCode.Assert();
            return AsNativeAccessible(publicIAccessible.accSelection);
        }
 
        object UnsafeNativeMethods.IAccessibleInternal.get_accState(object childID) {
            IntSecurity.UnmanagedCode.Assert();
            return publicIAccessible.get_accState(childID);
        }
 
        string UnsafeNativeMethods.IAccessibleInternal.get_accValue(object childID) {
            IntSecurity.UnmanagedCode.Assert();
            return publicIAccessible.get_accValue(childID);
        }
 
        void UnsafeNativeMethods.IAccessibleInternal.set_accName(Object childID, string newName) {
            IntSecurity.UnmanagedCode.Assert();
            publicIAccessible.set_accName(childID, newName);
        }
 
        void UnsafeNativeMethods.IAccessibleInternal.set_accValue(Object childID, string newValue) {
            IntSecurity.UnmanagedCode.Assert();
            publicIAccessible.set_accValue(childID, newValue);
        }
 
        //
        // IEnumVariant implementation...
        //
 
        void UnsafeNativeMethods.IEnumVariant.Clone(UnsafeNativeMethods.IEnumVariant[] v) {
            IntSecurity.UnmanagedCode.Assert();
            publicIEnumVariant.Clone(v);
        }
 
        int UnsafeNativeMethods.IEnumVariant.Next(int n, IntPtr rgvar, int[] ns) {
            IntSecurity.UnmanagedCode.Assert();
            return publicIEnumVariant.Next(n, rgvar, ns);
        }
 
        void UnsafeNativeMethods.IEnumVariant.Reset() {
            IntSecurity.UnmanagedCode.Assert();
            publicIEnumVariant.Reset();
        }
 
        void UnsafeNativeMethods.IEnumVariant.Skip(int n) {
            IntSecurity.UnmanagedCode.Assert();
            publicIEnumVariant.Skip(n);
        }
 
        //
        // IOleWindow implementation...
        //
 
        int UnsafeNativeMethods.IOleWindow.GetWindow(out IntPtr hwnd) {
            IntSecurity.UnmanagedCode.Assert();
            return publicIOleWindow.GetWindow(out hwnd);
        }
 
        void UnsafeNativeMethods.IOleWindow.ContextSensitiveHelp(int fEnterMode) {
            IntSecurity.UnmanagedCode.Assert();
            publicIOleWindow.ContextSensitiveHelp(fEnterMode);
        }
 
        //
        // IReflect implementation...
        //
 
        MethodInfo IReflect.GetMethod(string name, BindingFlags bindingAttr, Binder binder, Type[] types, ParameterModifier[] modifiers) {
            return publicIReflect.GetMethod(name, bindingAttr, binder, types, modifiers);
        }
 
        MethodInfo IReflect.GetMethod(string name, BindingFlags bindingAttr) {
            return publicIReflect.GetMethod(name, bindingAttr);
        }
 
        MethodInfo[] IReflect.GetMethods(BindingFlags bindingAttr) {
            return publicIReflect.GetMethods(bindingAttr);
        }
 
        FieldInfo IReflect.GetField(string name, BindingFlags bindingAttr) {
            return publicIReflect.GetField(name, bindingAttr);
        }
 
        FieldInfo[] IReflect.GetFields(BindingFlags bindingAttr) {
            return publicIReflect.GetFields(bindingAttr);
        }
 
        PropertyInfo IReflect.GetProperty(string name, BindingFlags bindingAttr) {
            return publicIReflect.GetProperty(name, bindingAttr);
        }
 
        PropertyInfo IReflect.GetProperty(string name, BindingFlags bindingAttr, Binder binder, Type returnType, Type[] types, ParameterModifier[] modifiers) {
            return publicIReflect.GetProperty(name, bindingAttr, binder, returnType, types, modifiers);
        }
 
        PropertyInfo[] IReflect.GetProperties(BindingFlags bindingAttr) {
            return publicIReflect.GetProperties(bindingAttr);
        }
 
        MemberInfo[] IReflect.GetMember(string name, BindingFlags bindingAttr) {
            return publicIReflect.GetMember(name, bindingAttr);
        }
 
        MemberInfo[] IReflect.GetMembers(BindingFlags bindingAttr) {
            return publicIReflect.GetMembers(bindingAttr);
        }
 
        object IReflect.InvokeMember(string name, BindingFlags invokeAttr, Binder binder, object target, object[] args, ParameterModifier[] modifiers, CultureInfo culture, string[] namedParameters) {
            IntSecurity.UnmanagedCode.Demand();
            return publicIReflect.InvokeMember(name, invokeAttr, binder, publicIAccessible, args, modifiers, culture, namedParameters);
        }
 
        Type IReflect.UnderlyingSystemType {
            get {
                IReflect r = publicIReflect;
                return publicIReflect.UnderlyingSystemType;
            }
        }
 
        //
        // IServiceProvider implementation
        //
 
        int UnsafeNativeMethods.IServiceProvider.QueryService(ref Guid service, ref Guid riid, out IntPtr ppvObject) {
            IntSecurity.UnmanagedCode.Assert();
 
            ppvObject = IntPtr.Zero;
            int hr = publicIServiceProvider.QueryService(ref service, ref riid, out ppvObject);
            if (hr >= NativeMethods.S_OK) {
                // we always want to return the internal accessible object
                ppvObject = Marshal.GetComInterfaceForObject(this, typeof(UnsafeNativeMethods.IAccessibleEx));
            }
 
            return hr;
        }
 
        //
        // IAccessibleEx implementation
        //
 
        object UnsafeNativeMethods.IAccessibleEx.GetObjectForChild(int idChild) {
            IntSecurity.UnmanagedCode.Assert();
            return publicIAccessibleEx.GetObjectForChild(idChild);
        }
 
        int UnsafeNativeMethods.IAccessibleEx.GetIAccessiblePair(out object ppAcc, out int pidChild) {
 
            IntSecurity.UnmanagedCode.Assert();
 
            // We always want to return the internal accessible object
            ppAcc = this;
            pidChild = NativeMethods.CHILDID_SELF;
            return NativeMethods.S_OK;
        }
 
        int[] UnsafeNativeMethods.IAccessibleEx.GetRuntimeId() {
 
            IntSecurity.UnmanagedCode.Assert();
            return publicIAccessibleEx.GetRuntimeId();
        }
 
        int UnsafeNativeMethods.IAccessibleEx.ConvertReturnedElement(object pIn, out object ppRetValOut) {
 
            IntSecurity.UnmanagedCode.Assert();
            return publicIAccessibleEx.ConvertReturnedElement(pIn, out ppRetValOut);
        }
 
        //
        // IRawElementProviderSimple implementation
        //
 
        UnsafeNativeMethods.ProviderOptions UnsafeNativeMethods.IRawElementProviderSimple.ProviderOptions {
            get {
                IntSecurity.UnmanagedCode.Assert();
                return publicIRawElementProviderSimple.ProviderOptions;
            }
        }
 
        UnsafeNativeMethods.IRawElementProviderSimple UnsafeNativeMethods.IRawElementProviderSimple.HostRawElementProvider {
            get {
                IntSecurity.UnmanagedCode.Assert();
                return publicIRawElementProviderSimple.HostRawElementProvider;
            }
        }
 
        object UnsafeNativeMethods.IRawElementProviderSimple.GetPatternProvider(int patternId) {
            IntSecurity.UnmanagedCode.Assert();
 
            object obj = publicIRawElementProviderSimple.GetPatternProvider(patternId);
            if (obj != null) {
 
                // we always want to return the internal accessible object
 
                if (patternId == NativeMethods.UIA_ExpandCollapsePatternId) {
                    return (UnsafeNativeMethods.IExpandCollapseProvider)this;
                }
                else if (patternId == NativeMethods.UIA_ValuePatternId) {
                    return (UnsafeNativeMethods.IValueProvider)this;
                }
                else if (AccessibilityImprovements.Level3 && patternId == NativeMethods.UIA_RangeValuePatternId) {
                    return (UnsafeNativeMethods.IRangeValueProvider)this;
                }
                else if (patternId == NativeMethods.UIA_TogglePatternId) {
                    return (UnsafeNativeMethods.IToggleProvider)this;
                }
                else if (patternId == NativeMethods.UIA_TablePatternId) {
                    return (UnsafeNativeMethods.ITableProvider)this;
                }
                else if (patternId == NativeMethods.UIA_TableItemPatternId) {
                    return (UnsafeNativeMethods.ITableItemProvider)this;
                }
                else if (patternId == NativeMethods.UIA_GridPatternId) {
                    return (UnsafeNativeMethods.IGridProvider)this;
                }
                else if (patternId == NativeMethods.UIA_GridItemPatternId) {
                    return (UnsafeNativeMethods.IGridItemProvider)this;
                }
                else if (AccessibilityImprovements.Level3 && patternId == NativeMethods.UIA_InvokePatternId) {
                    return (UnsafeNativeMethods.IInvokeProvider)this;
                }
                else if (AccessibilityImprovements.Level3 && patternId == NativeMethods.UIA_LegacyIAccessiblePatternId) {
                    return (UnsafeNativeMethods.ILegacyIAccessibleProvider)this;
                }
                else if (AccessibilityImprovements.Level3 && patternId == NativeMethods.UIA_SelectionPatternId) {
                    return (UnsafeNativeMethods.ISelectionProvider)this;
                }
                else if (AccessibilityImprovements.Level3 && patternId == NativeMethods.UIA_SelectionItemPatternId) {
                    return (UnsafeNativeMethods.ISelectionItemProvider)this;
                }
                else {
                    return null;
                }
            }
            else {
                return null;
            }
        }
 
        object UnsafeNativeMethods.IRawElementProviderSimple.GetPropertyValue(int propertyID) {
            IntSecurity.UnmanagedCode.Assert();
            return publicIRawElementProviderSimple.GetPropertyValue(propertyID);
        }
 
        //
        // IRawElementProviderFragment implementation
        //
 
        object UnsafeNativeMethods.IRawElementProviderFragment.Navigate(UnsafeNativeMethods.NavigateDirection direction) {
            IntSecurity.UnmanagedCode.Assert();
            return AsNativeAccessible(publicIRawElementProviderFragment.Navigate(direction));
        }
 
        int[] UnsafeNativeMethods.IRawElementProviderFragment.GetRuntimeId() {
            IntSecurity.UnmanagedCode.Assert();
            return publicIRawElementProviderFragment.GetRuntimeId();
        }
 
        object[] UnsafeNativeMethods.IRawElementProviderFragment.GetEmbeddedFragmentRoots() {
            IntSecurity.UnmanagedCode.Assert();
            return AsArrayOfNativeAccessibles(publicIRawElementProviderFragment.GetEmbeddedFragmentRoots());
        }
 
        void UnsafeNativeMethods.IRawElementProviderFragment.SetFocus() {
            IntSecurity.UnmanagedCode.Assert();
            publicIRawElementProviderFragment.SetFocus();
        }
 
        NativeMethods.UiaRect UnsafeNativeMethods.IRawElementProviderFragment.BoundingRectangle {
            get {
                IntSecurity.UnmanagedCode.Assert();
                return publicIRawElementProviderFragment.BoundingRectangle;
            }
        }
 
        UnsafeNativeMethods.IRawElementProviderFragmentRoot UnsafeNativeMethods.IRawElementProviderFragment.FragmentRoot {
            get {
                IntSecurity.UnmanagedCode.Assert();
                if (AccessibilityImprovements.Level3) {
                    return publicIRawElementProviderFragment.FragmentRoot;
                }
 
                return AsNativeAccessible(publicIRawElementProviderFragment.FragmentRoot) as UnsafeNativeMethods.IRawElementProviderFragmentRoot;
            }
        }
 
        //
        // IRawElementProviderFragmentRoot implementation
        //
 
        object UnsafeNativeMethods.IRawElementProviderFragmentRoot.ElementProviderFromPoint(double x, double y) {
            IntSecurity.UnmanagedCode.Assert();
            return AsNativeAccessible(publicIRawElementProviderFragmentRoot.ElementProviderFromPoint(x, y));
        }
 
        object UnsafeNativeMethods.IRawElementProviderFragmentRoot.GetFocus() {
            IntSecurity.UnmanagedCode.Assert();
            return AsNativeAccessible(publicIRawElementProviderFragmentRoot.GetFocus());
        }
 
        //
        // ILegacyIAccessibleProvider implementation
        //
 
        string UnsafeNativeMethods.ILegacyIAccessibleProvider.DefaultAction {
            get {
                IntSecurity.UnmanagedCode.Assert();
                return publicILegacyIAccessibleProvider.DefaultAction;
            }
        }
 
        string UnsafeNativeMethods.ILegacyIAccessibleProvider.Description {
            get {
                IntSecurity.UnmanagedCode.Assert();
                return publicILegacyIAccessibleProvider.Description;
            }
        }
 
        string UnsafeNativeMethods.ILegacyIAccessibleProvider.Help {
            get {
                IntSecurity.UnmanagedCode.Assert();
                return publicILegacyIAccessibleProvider.Help;
            }
        }
 
        string UnsafeNativeMethods.ILegacyIAccessibleProvider.KeyboardShortcut {
            get {
                IntSecurity.UnmanagedCode.Assert();
                return publicILegacyIAccessibleProvider.KeyboardShortcut;
            }
        }
 
        string UnsafeNativeMethods.ILegacyIAccessibleProvider.Name {
            get {
                IntSecurity.UnmanagedCode.Assert();
                return publicILegacyIAccessibleProvider.Name;
            }
        }
 
        uint UnsafeNativeMethods.ILegacyIAccessibleProvider.Role {
            get {
                IntSecurity.UnmanagedCode.Assert();
                return publicILegacyIAccessibleProvider.Role;
            }
        }
 
        uint UnsafeNativeMethods.ILegacyIAccessibleProvider.State {
            get {
                IntSecurity.UnmanagedCode.Assert();
                return publicILegacyIAccessibleProvider.State;
            }
        }
 
        string UnsafeNativeMethods.ILegacyIAccessibleProvider.Value {
            get {
                IntSecurity.UnmanagedCode.Assert();
                return publicILegacyIAccessibleProvider.Value;
            }
        }
 
        int UnsafeNativeMethods.ILegacyIAccessibleProvider.ChildId {
            get {
                IntSecurity.UnmanagedCode.Assert();
                return publicILegacyIAccessibleProvider.ChildId;
            }
        }
 
        void UnsafeNativeMethods.ILegacyIAccessibleProvider.DoDefaultAction() {
            IntSecurity.UnmanagedCode.Assert();
            publicILegacyIAccessibleProvider.DoDefaultAction();
        }
 
        IAccessible UnsafeNativeMethods.ILegacyIAccessibleProvider.GetIAccessible() {
            IntSecurity.UnmanagedCode.Assert();
            return publicILegacyIAccessibleProvider.GetIAccessible();
        }
 
        object[] UnsafeNativeMethods.ILegacyIAccessibleProvider.GetSelection() {
            IntSecurity.UnmanagedCode.Assert();
            return AsArrayOfNativeAccessibles(publicILegacyIAccessibleProvider.GetSelection());
        }
 
        void UnsafeNativeMethods.ILegacyIAccessibleProvider.Select(int flagsSelect) {
            IntSecurity.UnmanagedCode.Assert();
            publicILegacyIAccessibleProvider.Select(flagsSelect);
        }
 
        void UnsafeNativeMethods.ILegacyIAccessibleProvider.SetValue(string szValue) {
            IntSecurity.UnmanagedCode.Assert();
            publicILegacyIAccessibleProvider.SetValue(szValue);
        }
 
        //
        // IInvokeProvider implementation
        //
 
        void UnsafeNativeMethods.IInvokeProvider.Invoke() {
            IntSecurity.UnmanagedCode.Assert();
            publicIInvokeProvider.Invoke();
        }
 
        //
        // IValueProvider implementation
        //
 
        bool UnsafeNativeMethods.IValueProvider.IsReadOnly {
            get {
                IntSecurity.UnmanagedCode.Assert();
                return publicIValueProvider.IsReadOnly;
            }
        }
 
        string UnsafeNativeMethods.IValueProvider.Value {
            get {
                IntSecurity.UnmanagedCode.Assert();
                return publicIValueProvider.Value;
            }
        }
 
        void UnsafeNativeMethods.IValueProvider.SetValue(string newValue) {
            IntSecurity.UnmanagedCode.Assert();
            publicIValueProvider.SetValue(newValue);
        }
 
        //
        // IRangeValueProvider implementation
        //
 
        bool UnsafeNativeMethods.IRangeValueProvider.IsReadOnly {
            get {
                IntSecurity.UnmanagedCode.Assert();
                return publicIValueProvider.IsReadOnly;
            }
        }
 
        double UnsafeNativeMethods.IRangeValueProvider.LargeChange {
            get {
                IntSecurity.UnmanagedCode.Assert();
                return publicIRangeValueProvider.LargeChange;
            }
        }
 
        double UnsafeNativeMethods.IRangeValueProvider.Maximum {
            get {
                IntSecurity.UnmanagedCode.Assert();
                return publicIRangeValueProvider.Maximum;
            }
        }
 
        double UnsafeNativeMethods.IRangeValueProvider.Minimum {
            get {
                IntSecurity.UnmanagedCode.Assert();
                return publicIRangeValueProvider.Minimum;
            }
        }
 
        double UnsafeNativeMethods.IRangeValueProvider.SmallChange {
            get {
                IntSecurity.UnmanagedCode.Assert();
                return publicIRangeValueProvider.SmallChange;
            }
        }
 
        double UnsafeNativeMethods.IRangeValueProvider.Value {
            get {
                IntSecurity.UnmanagedCode.Assert();
                return publicIRangeValueProvider.Value;
            }
        }
 
        void UnsafeNativeMethods.IRangeValueProvider.SetValue(double newValue) {
            IntSecurity.UnmanagedCode.Assert();
            publicIRangeValueProvider.SetValue(newValue);
        }
 
        //
        // IExpandCollapseProvider implementation
        //
 
        void UnsafeNativeMethods.IExpandCollapseProvider.Expand() {
            IntSecurity.UnmanagedCode.Assert();
            publicIExpandCollapseProvider.Expand();
        }
 
        void UnsafeNativeMethods.IExpandCollapseProvider.Collapse() {
            IntSecurity.UnmanagedCode.Assert();
            publicIExpandCollapseProvider.Collapse();
        }
 
        UnsafeNativeMethods.ExpandCollapseState UnsafeNativeMethods.IExpandCollapseProvider.ExpandCollapseState {
            get {
                IntSecurity.UnmanagedCode.Assert();
                return publicIExpandCollapseProvider.ExpandCollapseState;
            }
        }
 
        //
        // IToggleProvider implementation
        //
 
        void UnsafeNativeMethods.IToggleProvider.Toggle() {
            IntSecurity.UnmanagedCode.Assert();
            publicIToggleProvider.Toggle();
        }
 
        UnsafeNativeMethods.ToggleState UnsafeNativeMethods.IToggleProvider.ToggleState {
            get {
                IntSecurity.UnmanagedCode.Assert();
                return publicIToggleProvider.ToggleState;
            }
        }
 
        //
        // ITableProvider implementation
        //
 
        object[] UnsafeNativeMethods.ITableProvider.GetRowHeaders() {
            IntSecurity.UnmanagedCode.Assert();
            return AsArrayOfNativeAccessibles(publicITableProvider.GetRowHeaders());
        }
 
        object[] UnsafeNativeMethods.ITableProvider.GetColumnHeaders() {
            IntSecurity.UnmanagedCode.Assert();
            return AsArrayOfNativeAccessibles(publicITableProvider.GetColumnHeaders());
        }
 
        UnsafeNativeMethods.RowOrColumnMajor UnsafeNativeMethods.ITableProvider.RowOrColumnMajor {
            get {
                IntSecurity.UnmanagedCode.Assert();
                return publicITableProvider.RowOrColumnMajor;
            }
        }
 
        //
        // ITableItemProvider implementation
        //
 
        object[] UnsafeNativeMethods.ITableItemProvider.GetRowHeaderItems() {
            IntSecurity.UnmanagedCode.Assert();
            return AsArrayOfNativeAccessibles(publicITableItemProvider.GetRowHeaderItems());
        }
 
        object[] UnsafeNativeMethods.ITableItemProvider.GetColumnHeaderItems() {
            IntSecurity.UnmanagedCode.Assert();
            return AsArrayOfNativeAccessibles(publicITableItemProvider.GetColumnHeaderItems());
        }
 
        //
        // IGridProvider implementation
        //
 
        object UnsafeNativeMethods.IGridProvider.GetItem(int row, int column) {
            IntSecurity.UnmanagedCode.Assert();
            return AsNativeAccessible(publicIGridProvider.GetItem(row, column));
        }
 
        int UnsafeNativeMethods.IGridProvider.RowCount {
            get {
                IntSecurity.UnmanagedCode.Assert();
                return publicIGridProvider.RowCount;
            }
        }
 
        int UnsafeNativeMethods.IGridProvider.ColumnCount {
            get {
                IntSecurity.UnmanagedCode.Assert();
                return publicIGridProvider.ColumnCount;
            }
        }
 
        //
        // IGridItemProvider implementation
        //
                
        int UnsafeNativeMethods.IGridItemProvider.Row {
            get {
                IntSecurity.UnmanagedCode.Assert();
                return publicIGridItemProvider.Row;
            }
        }
 
        int UnsafeNativeMethods.IGridItemProvider.Column {
            get {
                IntSecurity.UnmanagedCode.Assert();
                return publicIGridItemProvider.Column;
            }
        }
 
        int UnsafeNativeMethods.IGridItemProvider.RowSpan {
            get {
                IntSecurity.UnmanagedCode.Assert();
                return publicIGridItemProvider.RowSpan;
            }
        }
 
        int UnsafeNativeMethods.IGridItemProvider.ColumnSpan {
            get {
                IntSecurity.UnmanagedCode.Assert();
                return publicIGridItemProvider.ColumnSpan;
            }
        }
 
        UnsafeNativeMethods.IRawElementProviderSimple UnsafeNativeMethods.IGridItemProvider.ContainingGrid {
            get {
                IntSecurity.UnmanagedCode.Assert();
 
                // Do not wrap returned UIA provider by InternalAccessibleObject in Level 3.
                if (AccessibilityImprovements.Level3) {
                    return publicIGridItemProvider.ContainingGrid;
                }
 
                return AsNativeAccessible(publicIGridItemProvider.ContainingGrid) as UnsafeNativeMethods.IRawElementProviderSimple;
            }
        }
 
        //
        // ISelectionProvider implementation
        //
 
        /// <summary>
        /// Get the currently selected elements
        /// </summary>
        /// <returns>An AutomationElement array containing the currently selected elements</returns>
        object[] UnsafeNativeMethods.ISelectionProvider.GetSelection() {
            IntSecurity.UnmanagedCode.Assert();
            return publicISelectionProvider.GetSelection();
        }
 
        /// <summary>
        /// Indicates whether the control allows more than one element to be selected
        /// </summary>
        /// <returns>Boolean indicating whether the control allows more than one element to be selected</returns>
        /// <remarks>If this is false, then the control is a single-select ccntrol</remarks>
        bool UnsafeNativeMethods.ISelectionProvider.CanSelectMultiple {
            get {
                IntSecurity.UnmanagedCode.Assert();
                return publicISelectionProvider.CanSelectMultiple;
            }
        }
 
        /// <summary>
        /// Indicates whether the control requires at least one element to be selected
        /// </summary>
        /// <returns>Boolean indicating whether the control requires at least one element to be selected</returns>
        /// <remarks>If this is false, then the control allows all elements to be unselected</remarks>
        bool UnsafeNativeMethods.ISelectionProvider.IsSelectionRequired {
            get {
                IntSecurity.UnmanagedCode.Assert();
                return publicISelectionProvider.IsSelectionRequired;
            }
        }
 
        //
        // ISelectionItemProvider implementation
        //
 
        /// <summary>
        /// Sets the current element as the selection
        /// This clears the selection from other elements in the container.
        /// </summary>
        void UnsafeNativeMethods.ISelectionItemProvider.Select() {
            IntSecurity.UnmanagedCode.Assert();
            publicISelectionItemProvider.Select();
        }
 
        /// <summary>
        /// Adds current element to selection.
        /// </summary>
        void UnsafeNativeMethods.ISelectionItemProvider.AddToSelection() {
            IntSecurity.UnmanagedCode.Assert();
            publicISelectionItemProvider.AddToSelection();
        }
 
        /// <summary>
        /// Removes current element from selection.
        /// </summary>
        void UnsafeNativeMethods.ISelectionItemProvider.RemoveFromSelection() {
            IntSecurity.UnmanagedCode.Assert();
            publicISelectionItemProvider.RemoveFromSelection();
        }
 
        /// <summary>
        /// Check whether an element is selected.
        /// </summary>
        /// <returns>Returns true if the element is selected.</returns>
        bool UnsafeNativeMethods.ISelectionItemProvider.IsSelected {
            get {
                IntSecurity.UnmanagedCode.Assert();
                return publicISelectionItemProvider.IsSelected;
            }
        }
 
        /// <summary>
        /// The logical element that supports the SelectionPattern for this Item.
        /// </summary>
        /// <returns>Returns a IRawElementProviderSimple.</returns>
        UnsafeNativeMethods.IRawElementProviderSimple UnsafeNativeMethods.ISelectionItemProvider.SelectionContainer {
            get {
                IntSecurity.UnmanagedCode.Assert();
                return publicISelectionItemProvider.SelectionContainer;
            }
        }
 
        //
        // IRawElementProviderHwndOverride implementation
        //
 
        /// <summary>
        /// Request a provider for the specified component. The returned provider can supply additional
        /// properties or override properties of the specified component.
        /// </summary>
        /// <param name="hwnd">The window handle of the component.</param>
        /// <returns>Return the provider for the specified component, or null if the component is not being overridden.</returns>
        UnsafeNativeMethods.IRawElementProviderSimple UnsafeNativeMethods.IRawElementProviderHwndOverride.GetOverrideProviderForHwnd(IntPtr hwnd) {
            IntSecurity.UnmanagedCode.Assert();
            return publicIRawElementProviderHwndOverride.GetOverrideProviderForHwnd(hwnd);
        }
 
    } // end class InternalAccessibleObject
 
}