//------------------------------------------------------
        //
        //  Constructors
        //
        //------------------------------------------------------
 
        #region Constructors

        // primary ctor used to create all providers for IAccessible objects.
        // hwnd is the window this object belongs to.
        // root is a provider for the OBJID_CLIENT of the window. may be null if it is not yet known.
        // don't call this constructor directly -- call a Create or Wrap function below.
        protected MsaaNativeProvider(Accessible acc, IntPtr hwnd, MsaaNativeProvider parent, MsaaNativeProvider knownRoot, RootStatus isRoot)
        {
            Debug.Assert(acc != null, "acc");
            Debug.Assert(hwnd != IntPtr.Zero);

            _acc = acc;
            _hwnd = hwnd;

            _parent = parent; // can be null if not known.
            _knownRoot = knownRoot; // can be null if not known.
            _isRoot = isRoot; // can be RootStatus.Unknown
            // _controlType defaults to null. computed on demand.
        }
        //------------------------------------------------------
        //
        //  Internal Methods
        //
        //------------------------------------------------------
 
        #region Internal Methods

        // the creation of any msaa-based provider funnels through this function.
        // it creates an object of the base or correct derived class for the specified IAccessible object.
        private static MsaaNativeProvider Wrap(Accessible acc, IntPtr hwnd, MsaaNativeProvider parent, MsaaNativeProvider knownRoot, RootStatus isRoot)
        {
            // if acc is null then return null.
            if (acc == null)
                return null;

            // check that parent is actually our parent - sometimes hit-test and navigation skip layers, so we
            // may need to reconstruct the parent chain to account for skipped-over ancestors: keep climbing
            // upwards till we reach the 'parent' that was passed in...
            MsaaNativeProvider parentChain = parent;
            if (parent != null)
            {
                ArrayList actualParentChain = null;
                Accessible scan = acc.Parent;
                while (scan != null)
                {
                    if (Accessible.Compare(scan, parent._acc))
                        break; // found actual parent
                    // found intermediate ancestor - add to list...
                    if (actualParentChain == null)
                        actualParentChain = new ArrayList();
                    actualParentChain.Add(scan);
                    scan = scan.Parent;
                }

                if (actualParentChain != null)
                {
                    // if we found intermediate ancestors, process them top-down, creating
                    // MsaaNativeProviders for each in turn, using the bottom-most one as
                    // our own actual parent...
                    for (int i = actualParentChain.Count - 1; i >= 0; i--)
                    {
                        Accessible ancestor = (Accessible)actualParentChain[i];
                        parentChain = new MsaaNativeProvider(ancestor, hwnd, parentChain, knownRoot, isRoot);
                    }
                }
            }

            return new MsaaNativeProvider(acc, hwnd, parentChain, knownRoot, isRoot);
        }