Misc.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / Orcas / SP / wpf / src / UIAutomation / Win32Providers / MS / Internal / AutomationProxies / Misc.cs / 1 / Misc.cs

                            //---------------------------------------------------------------------------- 
//
// 
//    Copyright (C) Microsoft Corporation.  All rights reserved.
//  
//
// 
// Description: Miscellaneous helper routines 
//
// History: 
//  12/06/2004 : Created [....]
//
//---------------------------------------------------------------------------
 

// PRESHARP: In order to avoid generating warnings about unkown message numbers and unknown pragmas. 
#pragma warning disable 1634, 1691 

using Microsoft.Win32.SafeHandles; 
using MS.Win32;
using System;
using System.Collections;
using System.ComponentModel; 
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; 
using System.Security.Permissions; 
using System.Text;
using System.Windows.Automation; 
using System.Windows.Automation.Provider;
using System.Windows;
using System.Windows.Input;
using System.Diagnostics; 

namespace MS.Internal.AutomationProxies 
{ 
    static class Misc
    { 

        //-----------------------------------------------------
        //
        //  Internal Methods 
        //
        //----------------------------------------------------- 
 
        #region Internal Methods
 
        //
        //  HrGetWindowShortcut()
        //
        internal static string AccessKey(string s) 
        {
            // Get the index of the shortcut 
            int iPosShortCut = s.IndexOf('&'); 

            // Did we found an & or is it at the end of the string 
            if (iPosShortCut < 0 || iPosShortCut + 1 >= s.Length)
            {
                return null;
            } 

            // Build the result string 
            return ST.Get(STID.KeyAlt) + "+" + s[iPosShortCut + 1]; 
        }
 
        // Extend an existing RunTimeID by one element
        internal static int[] AppendToRuntimeId(int[] baseID, int id)
        {
            // For the base case, where parent is a hwnd, baseID will be null, 
            // so use AppendRuntimeId instead. UIA will then glue that to the ID
            // of the parent HWND. 
            if(baseID == null) 
                baseID = new int[] { AutomationInteropProvider.AppendRuntimeId };
 
            int len = baseID.Length;
            int[] newID = new int[len + 1];

            baseID.CopyTo(newID, 0); 
            newID[len] = id;
            return newID; 
        } 

        internal static double[] RectArrayToDoubleArray(Rect[] rectArray) 
        {
            if (rectArray == null)
                return null;
            double[] doubles = new double[rectArray.Length * 4]; 
            int scan = 0;
            for (int i = 0; i < rectArray.Length; i++) 
            { 
                doubles[scan++] = rectArray[i].X;
                doubles[scan++] = rectArray[i].Y; 
                doubles[scan++] = rectArray[i].Width;
                doubles[scan++] = rectArray[i].Height;
            }
            return doubles; 
        }
 
        // Ensure a window and all its parents are enabled. 
        // If not, throw ElementNotEnabledException.
        internal static void CheckEnabled(IntPtr hwnd) 
        {
            if (!IsEnabled(hwnd))
            {
                throw new ElementNotEnabledException(); 
            }
        } 
 
        // Checks to see if the process owning the hwnd is currently in menu mode
        // and takes steps to exit menu mode if it is 
        internal static void ClearMenuMode()
        {
            // Check if we're in menu mode with helper method.
            if (InMenuMode()) 
            {
                // If we are, send an alt keypress to escape 
                Input.SendKeyboardInput(Key.LeftAlt, true); 
                Input.SendKeyboardInput(Key.LeftAlt, false);
 
                // Wait for a few milliseconds for this operation to be completed
                long dwTicks = (long)Environment.TickCount;

                // Wait until the action has been completed 
                while (InMenuMode() && ((long)Environment.TickCount - dwTicks) < MenuTimeOut)
                { 
                    // Sleep the shortest amount of time possible while still guaranteeing that some sleep occurs 
                    System.Threading.Thread.Sleep(1);
                } 
            }
        }

        internal static bool CloseHandle(IntPtr processHandle) 
        {
            bool result = UnsafeNativeMethods.CloseHandle(processHandle); 
            int lastWin32Error = Marshal.GetLastWin32Error(); 

            if (!result) 
            {
                ThrowWin32ExceptionsIfError(lastWin32Error);
            }
 
            return result;
        } 
 
        // Compares 2 raw elements and returns true if equal, false otherwise
        internal static bool Compare(ProxySimple el1, ProxySimple el2) 
        {
            int[] a1 = el1.GetRuntimeId();
            int[] a2 = el2.GetRuntimeId();
            int l = a1.Length; 

            if (l != a2.Length) 
                return false; 

            for (int i = 0; i < l; i++) 
            {
                if (a1[i] != a2[i])
                {
                    return false; 
                }
            } 
 
            return true;
        } 

        internal static IntPtr DispatchMessage(ref NativeMethods.MSG msg)
        {
            // From the Windows SDK documentation: 
            // The return value specifies the value returned by the window procedure.
            // Although its meaning depends on the message being dispatched, the return 
            // value generally is ignored. 
#pragma warning suppress 6031, 6523
            return UnsafeNativeMethods.DispatchMessage(ref msg); 
        }


        internal unsafe static bool EnumChildWindows(IntPtr hwnd, NativeMethods.EnumChildrenCallbackVoid lpEnumFunc, void* lParam) 
        {
            bool result = UnsafeNativeMethods.EnumChildWindows(hwnd, lpEnumFunc, lParam); 
            int lastWin32Error = Marshal.GetLastWin32Error(); 

            if (!result) 
            {
                ThrowWin32ExceptionsIfError(lastWin32Error);
            }
 
            return result;
        } 
 
        internal static IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string className, string wndName)
        { 
            // The failure case of this API may also be a valid return.  GetLastError() is need to determine a true failure state.
            // Clear the last error code to make sure we have a good starting condition to determine error state.
            UnsafeNativeMethods.SetLastError(0);
            IntPtr result = UnsafeNativeMethods.FindWindowEx(hwndParent, hwndChildAfter, className, wndName); 
            int lastWin32Error = Marshal.GetLastWin32Error();
 
            if (result == IntPtr.Zero) 
            {
                ThrowWin32ExceptionsIfError(lastWin32Error); 
            }

            return result;
        } 

        internal static string GetClassName(IntPtr hwnd) 
        { 
            StringBuilder sb = new StringBuilder(NativeMethods.MAX_PATH + 1);
 
            int result = UnsafeNativeMethods.GetClassName(hwnd, sb, NativeMethods.MAX_PATH);
            int lastWin32Error = Marshal.GetLastWin32Error();

            if (result == 0) 
            {
                ThrowWin32ExceptionsIfError(lastWin32Error); 
                return ""; 
            }
 
            return sb.ToString();
        }

        // Get the name of a control and conditionally strip mnemonic. 
        // label is the hwnd of the control that is funtioning as the label.  Use GetLabelhwnd to find this.
        // If stripMnemonic is true, amperstrands characters will be stripped out. 
        internal static string GetControlName(IntPtr label, bool stripMnemonic) 
        {
            if (label == IntPtr.Zero) 
            {
                return null;
            }
 
            StringBuilder sb = new StringBuilder(MaxLengthNameProperty);
 
            int result = UnsafeNativeMethods.GetWindowText(label, sb, MaxLengthNameProperty); 
            int lastWin32Error = Marshal.GetLastWin32Error();
 
            if (result == 0)
            {
                ThrowWin32ExceptionsIfError(lastWin32Error);
                return null; 
            }
 
            return stripMnemonic ? StripMnemonic(sb.ToString()) : sb.ToString(); 

        } 

        internal static bool GetClientRectInScreenCoordinates(IntPtr hwnd, ref NativeMethods.Win32Rect rc)
        {
            rc = NativeMethods.Win32Rect.Empty; 

            if (!GetClientRect(hwnd, ref rc)) 
            { 
                return false;
            } 

            NativeMethods.Win32Point leftTop = new NativeMethods.Win32Point(rc.left, rc.top);
            if (!MapWindowPoints(hwnd, IntPtr.Zero, ref leftTop, 1))
            { 
                return false;
            } 
 
            NativeMethods.Win32Point rightBottom = new NativeMethods.Win32Point(rc.right, rc.bottom);
            if (!MapWindowPoints(hwnd, IntPtr.Zero, ref rightBottom, 1)) 
            {
                return false;
            }
 
            rc = new NativeMethods.Win32Rect(leftTop.x, leftTop.y, rightBottom.x, rightBottom.y);
            return true; 
        } 

        internal static bool GetClientRect(IntPtr hwnd, ref NativeMethods.Win32Rect rc) 
        {
            bool result = UnsafeNativeMethods.GetClientRect(hwnd, ref rc);
            int lastWin32Error = Marshal.GetLastWin32Error();
 
            if (!result)
            { 
                ThrowWin32ExceptionsIfError(lastWin32Error); 
            }
 
            // When the control is right to left GetClentRect() will return a rectangle with left > right.
            // Normalize thesee rectangle back to left to right.
            rc.Normalize(IsLayoutRTL(hwnd));
 
            return result;
        } 
 
        internal static bool GetComboBoxInfo(IntPtr hwnd, ref NativeMethods.COMBOBOXINFO cbi)
        { 
            bool result = UnsafeNativeMethods.GetComboBoxInfo(hwnd, ref cbi);
            int lastWin32Error = Marshal.GetLastWin32Error();

            if (!result) 
            {
                ThrowWin32ExceptionsIfError(lastWin32Error); 
            } 

            return result; 
        }

        internal static bool GetCursorPos(ref NativeMethods.Win32Point pt)
        { 
            // Vista and beyond use GetPhysicalCursorPos which handles DPI issues
            bool result = (System.Environment.OSVersion.Version.Major >= 6) ? UnsafeNativeMethods.GetPhysicalCursorPos(ref pt) 
                                                                            : UnsafeNativeMethods.GetCursorPos(ref pt); 
            int lastWin32Error = Marshal.GetLastWin32Error();
 
            if (!result)
            {
                ThrowWin32ExceptionsIfError(lastWin32Error);
            } 

            return result; 
        } 

 
        internal static IntPtr GetDC(IntPtr hwnd)
        {
            IntPtr hdc = UnsafeNativeMethods.GetDC(hwnd);
            int lastWin32Error = Marshal.GetLastWin32Error(); 

            if (hdc == IntPtr.Zero) 
            { 
                ThrowWin32ExceptionsIfError(lastWin32Error);
            } 

            return hdc;
        }
 
        internal static IntPtr GetFocusedWindow()
        { 
            NativeMethods.GUITHREADINFO gui; 

            return ProxyGetGUIThreadInfo(0, out gui) ? gui.hwndFocus : IntPtr.Zero; 
        }

        internal static string GetItemToolTipText(IntPtr hwnd, IntPtr hwndToolTip, int item)
        { 
            if (hwndToolTip != IntPtr.Zero)
            { 
                // We've found the tooltip window, so we won't need to scan for it. 

                // Got a tooltip window - use it. 
                NativeMethods.TOOLINFO tool = new NativeMethods.TOOLINFO();
                tool.Init(Marshal.SizeOf(typeof(NativeMethods.TOOLINFO)));

                tool.hwnd = hwnd; 
                tool.uId = item;
 
                return XSendMessage.GetItemText(hwndToolTip, tool); 
            }
            else 
            {
                // Control doesn't know its tooltip window - instead scan for one...

                // Enum the top-level windows owned by this thread... 
                uint processId;
                uint threadId = GetWindowThreadProcessId(hwnd, out processId); 
 
                UnsafeNativeMethods.ENUMTOOLTIPWINDOWINFO info = new UnsafeNativeMethods.ENUMTOOLTIPWINDOWINFO();
                info.hwnd = hwnd; 
                info.id = item;
                info.name = "";

                UnsafeNativeMethods.EnumThreadWndProc enumToolTipWindows = new UnsafeNativeMethods.EnumThreadWndProc(EnumToolTipWindows); 
                GCHandle gch = GCHandle.Alloc(enumToolTipWindows);
                UnsafeNativeMethods.EnumThreadWindows(threadId, enumToolTipWindows, ref info); 
                gch.Free(); 

                return info.name; 
            }
        }

        // -------------------------------------------------------------------------- 
        //
        //  GetLabelhwnd() 
        // 
        //  This walks backwards among peer windows to find a static field.  It stops
        //  if it gets to the front or hits a group/tabstop, just like the dialog 
        //  manager does.
        //
        // Ported from OleAcc\Client.CPP
        // ------------------------------------------------------------------------- 

        internal static IntPtr GetLabelhwnd(IntPtr hwnd) 
        { 
            // Sanity check
            if (!UnsafeNativeMethods.IsWindow(hwnd)) 
            {
                return IntPtr.Zero;
            }
 
            // Only get labels for child windows - not top-level windows or desktop
            IntPtr hwndParent = Misc.GetParent(hwnd); 
            if (hwndParent == IntPtr.Zero || hwndParent == UnsafeNativeMethods.GetDesktopWindow()) 
            {
                return IntPtr.Zero; 
            }

            IntPtr peer = hwnd;
 
            // If GetWindow fails we're going to exit, no need to call Marshal.GetLastWin32Error
#pragma warning suppress 56523 
            while ((peer = UnsafeNativeMethods.GetWindow(peer, NativeMethods.GW_HWNDPREV)) != IntPtr.Zero) 
            {
                // 
                // Is this a static dude?
                //
                int code = Misc.ProxySendMessageInt(peer, NativeMethods.WM_GETDLGCODE, IntPtr.Zero, IntPtr.Zero);
                if ((code & NativeMethods.DLGC_STATIC) == NativeMethods.DLGC_STATIC) 
                {
                    // 
                    // Great, we've found our label. 
                    //
                    return peer; 
                }

                //
                // Skip invisible controls. 
                // Note that we do this after checking if its a static, so that we give invisible statics a chance.
                // Using invisible statics is an easy workaround to add names to controls without changing the visual UI. 
                // 
                // If GetWindowLong fails we're going to exit, no need to call Marshal.GetLastWin32Error
#pragma warning suppress 56523 
                int style = UnsafeNativeMethods.GetWindowLong(peer, NativeMethods.GWL_STYLE);
                if ((style & NativeMethods.WS_VISIBLE) != 0)
                    continue;
 
                //
                // Is this a tabstop or group?  If so, bail out now. 
                // 
                if ((style & (NativeMethods.WS_GROUP | NativeMethods.WS_TABSTOP)) != 0)
                    break; 
            }

            // Failed to find a suitable peer
            return IntPtr.Zero; 
        }
 
        internal static bool GetMenuBarInfo(IntPtr hwnd, int idObject, uint item, ref NativeMethods.MENUBARINFO mbi) 
        {
            // The failure case of this API may also be a valid return.  GetLastError() is need to determine a true failure state. 
            // Clear the last error code to make sure we have a good starting condition to determine error state.
            UnsafeNativeMethods.SetLastError(0);
            bool result = UnsafeNativeMethods.GetMenuBarInfo(hwnd, idObject, item, ref mbi);
            int lastWin32Error = Marshal.GetLastWin32Error(); 

            if (!result) 
            { 
                ThrowWin32ExceptionsIfError(lastWin32Error);
            } 

            return result;
        }
 
        internal static int GetMenuItemCount(IntPtr hmenu)
        { 
            int count = UnsafeNativeMethods.GetMenuItemCount(hmenu); 
            int lastWin32Error = Marshal.GetLastWin32Error();
 
            if (count == -1)
            {
                ThrowWin32ExceptionsIfError(lastWin32Error);
            } 

            return count; 
        } 

        internal static bool GetMenuItemInfo(IntPtr hmenu, int item, bool byPosition, ref NativeMethods.MENUITEMINFO menuItemInfo) 
        {
            bool result = UnsafeNativeMethods.GetMenuItemInfo(hmenu, item, byPosition, ref menuItemInfo);
            int lastWin32Error = Marshal.GetLastWin32Error();
 
            if (!result)
            { 
                ThrowWin32ExceptionsIfError(lastWin32Error); 
            }
 
            return result;
        }

        internal static bool GetMenuItemRect(IntPtr hwnd, IntPtr hmenu, int item, out NativeMethods.Win32Rect rc) 
        {
            bool result = UnsafeNativeMethods.GetMenuItemRect(hwnd, hmenu, item, out rc); 
            int lastWin32Error = Marshal.GetLastWin32Error(); 

            if (!result) 
            {
                ThrowWin32ExceptionsIfError(lastWin32Error);
            }
 
            return result;
        } 
 
        internal static bool GetMessage(ref NativeMethods.MSG msg, IntPtr hwnd, int msgFilterMin, int msgFilterMax)
        { 
            int result = UnsafeNativeMethods.GetMessage(ref msg, hwnd, msgFilterMin, msgFilterMax);
            int lastWin32Error = Marshal.GetLastWin32Error();

            bool success = (result != 0 && result != -1); 
            if (!success)
            { 
                ThrowWin32ExceptionsIfError(lastWin32Error); 
            }
 
            return success;
        }

        internal static int GetObjectW(IntPtr hObject, int size, ref NativeMethods.LOGFONT lf) 
        {
            int result = UnsafeNativeMethods.GetObjectW(hObject, size, ref lf); 
            int lastWin32Error = Marshal.GetLastWin32Error(); 

            if (result == 0) 
            {
                ThrowWin32ExceptionsIfError(lastWin32Error);
            }
 
            return result;
        } 
 
        internal static IntPtr GetParent(IntPtr hwnd)
        { 
            // The failure case of this API may also be a valid return.  GetLastError() is need to determine a true failure state.
            // Clear the last error code to make sure we have a good starting condition to determine error state.
            UnsafeNativeMethods.SetLastError(0);
            IntPtr hwndParent = UnsafeNativeMethods.GetAncestor(hwnd, NativeMethods.GA_PARENT); 
            int lastWin32Error = Marshal.GetLastWin32Error();
 
            if (hwndParent == IntPtr.Zero) 
            {
                ThrowWin32ExceptionsIfError(lastWin32Error); 
            }

            return hwndParent;
        } 

        internal static bool GetScrollBarInfo(IntPtr hwnd, int fnBar, ref NativeMethods.ScrollBarInfo sbi) 
        { 
            bool result = UnsafeNativeMethods.GetScrollBarInfo(hwnd, fnBar, ref sbi);
            int lastWin32Error = Marshal.GetLastWin32Error(); 

            if (!result)
            {
                ThrowWin32ExceptionsIfError(lastWin32Error); 
            }
 
            return result; 
        }
 
        internal static bool GetScrollInfo(IntPtr hwnd, int fnBar, ref NativeMethods.ScrollInfo si)
        {
            bool result = UnsafeNativeMethods.GetScrollInfo(hwnd, fnBar, ref si);
            int lastWin32Error = Marshal.GetLastWin32Error(); 

            if (!result) 
            { 
                // 1447     ERROR_NO_SCROLLBARS     The window does not have scroll bars.
                // If GetScrollInfo() fails with ERROR_NO_SCROLLBARS then there is no scroll information 
                // to get.  Just return false saying that GetScrollInfo() could not get the information
                if (lastWin32Error == 1447)
                {
                    return false; 
                }
                ThrowWin32ExceptionsIfError(lastWin32Error); 
            } 

            return result; 
        }

        internal static int GetTextExtentPoint32(IntPtr hdc, string text, int length, out NativeMethods.SIZE size)
        { 
            // The failure case of this API may also be a valid return.  GetLastError() is need to determine a true failure state.
            // Clear the last error code to make sure we have a good starting condition to determine error state. 
            UnsafeNativeMethods.SetLastError(0); 
            int result = UnsafeNativeMethods.GetTextExtentPoint32(hdc, text, length, out size);
            int lastWin32Error = Marshal.GetLastWin32Error(); 

            if (result == 0)
            {
                ThrowWin32ExceptionsIfError(lastWin32Error); 
            }
 
            return result; 
        }
 
        // Calls a message that retrieves a string, but doesn't take a length argument, in a relatively safe manner.
        // Attempts to rapidly resize in hopes of crashing UI Automation should just crash whatever is rapidly resizing.
        // Param "hwnd" the Window Handle
        // Param "uMsg" the Windows Message 
        // Param "wParam" the Windows wParam
        // Param "maxLength" the size of the string 
        internal static unsafe string GetUnsafeText(IntPtr hwnd, int uMsg, IntPtr wParam, int maxLength) 
        {
            uint pageSize = GetPageSize(); 
            IntPtr memAddr = IntPtr.Zero;     // Ptr to remote mem
            // calculate the size needed for the string
            uint cbSize = (uint)((maxLength + 1) * sizeof(char));
            // resize it to include enough pages for the string, and an extra guarding page, and one extra page to account for shifts. 
            cbSize = ((cbSize / pageSize) + 3) * pageSize;
 
            try 
            {
                // Allocate the space 
                memAddr = VirtualAlloc(IntPtr.Zero, new UIntPtr(cbSize), UnsafeNativeMethods.MEM_COMMIT, UnsafeNativeMethods.PAGE_READWRITE);

                // Allocate the Final page as No Access, so any attempt to write to it will GPF
                VirtualAlloc(new IntPtr((byte *)memAddr.ToPointer() + cbSize - pageSize), new UIntPtr(pageSize), UnsafeNativeMethods.MEM_COMMIT, UnsafeNativeMethods.PAGE_NOACCESS); 

                // Send the message... 
                if (ProxySendMessage(hwnd, uMsg, wParam, memAddr) == IntPtr.Zero) 
                {
                    return ""; 
                }

                String str = new string((char*)memAddr.ToPointer(), 0, maxLength);
                // Note: lots of "old world" strings are null terminated 
                // Leaving the null termination in the System.String may lead
                // to some issues when used with the StringBuilder 
                int nullTermination = str.IndexOf('\0'); 

                if (-1 != nullTermination) 
                {
                    // We need to strip null terminated char and everything behind it from the str
                    str = str.Remove(nullTermination, maxLength - nullTermination);
                } 
                return str;
            } 
            finally 
            {
                // Free the memory 
                if (memAddr != IntPtr.Zero)
                {
                    VirtualFree(memAddr, UIntPtr.Zero, UnsafeNativeMethods.MEM_RELEASE);
                } 
            }
        } 
 
        internal static IntPtr GetWindow(IntPtr hwnd, int cmd)
        { 
            // The failure case of this API may also be a valid return.  GetLastError() is need to determine a true failure state.
            // Clear the last error code to make sure we have a good starting condition to determine error state.
            UnsafeNativeMethods.SetLastError(0);
            IntPtr resultHwnd = UnsafeNativeMethods.GetWindow(hwnd, cmd); 
            int lastWin32Error = Marshal.GetLastWin32Error();
 
            if (resultHwnd == IntPtr.Zero) 
            {
                ThrowWin32ExceptionsIfError(lastWin32Error); 
            }

            return resultHwnd;
        } 

        // Gets the extended style of the window 
        internal static int GetWindowExStyle(IntPtr hwnd) 
        {
            // The failure case of this API may also be a valid return.  GetLastError() is need to determine a true failure state. 
            // Clear the last error code to make sure we have a good starting condition to determine error state.
            UnsafeNativeMethods.SetLastError(0);
            int exstyle = UnsafeNativeMethods.GetWindowLong(hwnd, NativeMethods.GWL_EXSTYLE);
            int lastWin32Error = Marshal.GetLastWin32Error(); 

            if (exstyle == 0) 
            { 
                ThrowWin32ExceptionsIfError(lastWin32Error);
            } 

            return exstyle;
        }
 
        // Gets the id of the window
        internal static int GetWindowId(IntPtr hwnd) 
        { 
            // The failure case of this API may also be a valid return.  GetLastError() is need to determine a true failure state.
            // Clear the last error code to make sure we have a good starting condition to determine error state. 
            UnsafeNativeMethods.SetLastError(0);
            int id = UnsafeNativeMethods.GetWindowLong(hwnd, NativeMethods.GWL_ID);
            int lastWin32Error = Marshal.GetLastWin32Error();
 
            if (id == 0)
            { 
                ThrowWin32ExceptionsIfError(lastWin32Error); 
            }
 
            return id;
        }

        // Gets the parent of the window 
        internal static IntPtr GetWindowParent(IntPtr hwnd)
        { 
            // NOTE: This may have issues in 64-bit. 

            // The failure case of this API may also be a valid return.  GetLastError() is need to determine a true failure state. 
            // Clear the last error code to make sure we have a good starting condition to determine error state.
            UnsafeNativeMethods.SetLastError(0);
            int result = UnsafeNativeMethods.GetWindowLong(hwnd, NativeMethods.GWL_HWNDPARENT);
            int lastWin32Error = Marshal.GetLastWin32Error(); 

            if (result == 0) 
            { 
                ThrowWin32ExceptionsIfError(lastWin32Error);
            } 

            return (IntPtr)result;
        }
 
        internal static bool GetWindowRect(IntPtr hwnd, ref NativeMethods.Win32Rect rc)
        { 
            bool result = UnsafeNativeMethods.GetWindowRect(hwnd, ref rc); 
            int lastWin32Error = Marshal.GetLastWin32Error();
 
            if (!result)
            {
                ThrowWin32ExceptionsIfError(lastWin32Error);
            } 
            return result;
        } 
 
        // Gets the style of the window
        internal static int GetWindowStyle(IntPtr hwnd) 
        {
            // The failure case of this API may also be a valid return.  GetLastError() is need to determine a true failure state.
            // Clear the last error code to make sure we have a good starting condition to determine error state.
            UnsafeNativeMethods.SetLastError(0); 
            int style = UnsafeNativeMethods.GetWindowLong(hwnd, NativeMethods.GWL_STYLE);
            int lastWin32Error = Marshal.GetLastWin32Error(); 
 
            if (style == 0)
            { 
                ThrowWin32ExceptionsIfError(lastWin32Error);
            }

            return style; 
        }
 
        internal static uint GetWindowThreadProcessId(IntPtr hwnd, out uint processId) 
        {
            // GetWindowThreadProcessId does use SetLastError().  So a call to GetLastError() would be meanless. 
            // Disabling the PreSharp warning.
#pragma warning suppress 6523
            uint threadId = UnsafeNativeMethods.GetWindowThreadProcessId(hwnd, out processId);
 
            if (threadId == 0)
            { 
                throw new ElementNotAvailableException(); 
            }
 
            return threadId;
        }

        internal static short GlobalAddAtom(string atomName) 
        {
            short atom = UnsafeNativeMethods.GlobalAddAtom(atomName); 
            int lastWin32Error = Marshal.GetLastWin32Error(); 
            if (atom == 0)
            { 
                ThrowWin32ExceptionsIfError(lastWin32Error);
            }
            return atom;
        } 

        internal static short GlobalDeleteAtom(short atom) 
        { 
            // This API does not have an error condition.  GetLastError is used to determine if an error occured.
            // So, clear the last error code to make sure we have a good starting condition to determine error state. 
            UnsafeNativeMethods.SetLastError(0);
            short result = UnsafeNativeMethods.GlobalDeleteAtom(atom);
            ThrowWin32ExceptionsIfError(Marshal.GetLastWin32Error());
            return result; 
        }
 
        // detect if we're in the menu mode 
        internal static bool InMenuMode()
        { 
            NativeMethods.GUITHREADINFO gui;
            return (ProxyGetGUIThreadInfo(0, out gui) && (IsBitSet(gui.dwFlags, NativeMethods.GUI_INMENUMODE)));
        }
 
        internal static bool IsBitSet(int flags, int bit)
        { 
            return (flags & bit) == bit; 
        }
 
        // Check if window is really enabled, taking parent state into account.
        internal static bool IsEnabled(IntPtr hwnd)
        {
 
            // Navigate up parent chain. If any ancestor window is
            // not enabled, then that has the effect of disabling this window. 
            // All ancestor windows must be enabled for this window to be enabled. 
            for (; ; )
            { 
                if (!SafeNativeMethods.IsWindowEnabled(hwnd))
                {
                    return false;
                } 

                hwnd = UnsafeNativeMethods.GetAncestor(hwnd, NativeMethods.GA_PARENT); 
                if (hwnd == IntPtr.Zero) 
                {
                    return true; 
                }
            }
        }
 
        internal static bool IsControlRTL(IntPtr hwnd)
        { 
            int exStyle = GetWindowExStyle(hwnd); 
            return IsBitSet(exStyle, NativeMethods.WS_EX_LAYOUTRTL) || IsBitSet(exStyle, NativeMethods.WS_EX_RTLREADING);
        } 

        internal static bool IsLayoutRTL(IntPtr hwnd)
        {
            return IsBitSet(GetWindowExStyle(hwnd), NativeMethods.WS_EX_LAYOUTRTL); 
        }
 
        internal static bool IsReadingRTL(IntPtr hwnd) 
        {
            return IsBitSet(GetWindowExStyle(hwnd), NativeMethods.WS_EX_RTLREADING); 
        }

        internal static bool IntersectRect(ref NativeMethods.Win32Rect rcDest, ref NativeMethods.Win32Rect rc1, ref NativeMethods.Win32Rect rc2)
        { 
            bool result = SafeNativeMethods.IntersectRect(ref rcDest, ref rc1, ref rc2);
            int lastWin32Error = Marshal.GetLastWin32Error(); 
 
            if (!result)
            { 
                ThrowWin32ExceptionsIfError(lastWin32Error);
            }

            return result; 
        }
 
        // Call IsCriticalException w/in a catch-all-exception handler to allow critical exceptions 
        // to be thrown (this is copied from exception handling code in WinForms but feel free to
        // add new critical exceptions).  Usage: 
        //      try
        //      {
        //          Somecode();
        //      } 
        //      catch (Exception e)
        //      { 
        //          if (Misc.IsCriticalException(e)) 
        //              throw;
        //          // ignore non-critical errors from external code 
        //      }
        internal static bool IsCriticalException(Exception e)
        {
            return e is NullReferenceException || e is StackOverflowException || e is OutOfMemoryException || e is System.Threading.ThreadAbortException; 
        }
 
        // this is to determine is an item is visible.  The assumption is that the items here are not hwnds 
        // and that they are clipped by there parent.  For example this is called by the WindowsListBox.
        // In that case the hwnd is the list box and the itemRect would be a list item this code checks to see 
        // if the item is scrolled out of view.
        static internal bool IsItemVisible(IntPtr hwnd, ref NativeMethods.Win32Rect itemRect)
        {
            NativeMethods.Win32Rect clientRect = new NativeMethods.Win32Rect(0, 0, 0, 0); 
            if (!GetClientRectInScreenCoordinates(hwnd, ref clientRect))
                return false; 
 
            NativeMethods.Win32Rect intersection = new NativeMethods.Win32Rect(0, 0, 0, 0);
 
            // Returns true if the passed in itemRect overlaps with the client area of the hwnd this API
            // does not modify clientRect or itemRect
            return IntersectRect(ref intersection, ref clientRect, ref itemRect);
        } 

        static internal bool IsItemVisible(ref NativeMethods.Win32Rect parentRect, ref NativeMethods.Win32Rect itemRect) 
        { 
            NativeMethods.Win32Rect intersection = new NativeMethods.Win32Rect(0, 0, 0, 0);
 
            // Returns true if the passed in itemRect overlaps with the client area of the hwnd this API
            // does not modify clientRect or itemRect
            return IntersectRect(ref intersection, ref parentRect, ref itemRect);
        } 

        static internal bool IsItemVisible(ref NativeMethods.Win32Rect parentRect, ref Rect itemRect) 
        { 
            NativeMethods.Win32Rect itemRc = new NativeMethods.Win32Rect(itemRect);
            NativeMethods.Win32Rect intersection = new NativeMethods.Win32Rect(0, 0, 0, 0); 

            // Returns true if the passed in itemRect overlaps with the client area of the hwnd this API
            // does not modify clientRect or itemRect
            return IntersectRect(ref intersection, ref parentRect, ref itemRc); 
        }
 
        static internal bool IsItemVisible(ref Rect parentRect, ref NativeMethods.Win32Rect itemRect) 
        {
            NativeMethods.Win32Rect parentRc = new NativeMethods.Win32Rect(parentRect); 
            NativeMethods.Win32Rect intersection = new NativeMethods.Win32Rect(0, 0, 0, 0);

            // Returns true if the passed in itemRect overlaps with the client area of the hwnd this API
            // does not modify clientRect or itemRect 
            return IntersectRect(ref intersection, ref parentRc, ref itemRect);
        } 
 
        static internal bool IsItemVisible(ref Rect parentRect, ref Rect itemRect)
        { 
            NativeMethods.Win32Rect itemRc = new NativeMethods.Win32Rect(itemRect);
            NativeMethods.Win32Rect parentRc = new NativeMethods.Win32Rect(parentRect);
            NativeMethods.Win32Rect intersection = new NativeMethods.Win32Rect(0, 0, 0, 0);
 
            // Returns true if the passed in itemRect overlaps with the client area of the hwnd this API
            // does not modify clientRect or itemRect 
            return IntersectRect(ref intersection, ref parentRc, ref itemRc); 
        }
 
        internal static bool IsProgmanWindow(IntPtr hwnd)
        {
            while (hwnd != IntPtr.Zero)
            { 
                if (GetClassName(hwnd).CompareTo("Progman") == 0)
                { 
                    return true; 
                }
                hwnd = UnsafeNativeMethods.GetAncestor(hwnd, NativeMethods.GA_PARENT); 
            }
            return false;
        }
 
        internal static bool IsWow64Process(MS.Internal.AutomationProxies.SafeProcessHandle hProcess, out bool Wow64Process)
        { 
            bool result = UnsafeNativeMethods.IsWow64Process(hProcess, out Wow64Process); 
            int lastWin32Error = Marshal.GetLastWin32Error();
 
            if (!result)
            {
                ThrowWin32ExceptionsIfError(lastWin32Error);
            } 

            return result; 
        } 

        // wrapper for MapWindowPoints 
        internal static bool MapWindowPoints(IntPtr hWndFrom, IntPtr hWndTo, ref NativeMethods.Win32Rect rect, int cPoints)
        {
            // The failure case of this API may also be a valid return.  GetLastError() is need to determine a true failure state.
            // Clear the last error code to make sure we have a good starting condition to determine error state. 
            UnsafeNativeMethods.SetLastError(0);
            int mappingOffset = UnsafeNativeMethods.MapWindowPoints(hWndFrom, hWndTo, ref rect, cPoints); 
            int lastWin32Error = Marshal.GetLastWin32Error(); 
            if (mappingOffset == 0)
            { 
                // When mapping points to/from Progman and its children MapWindowPoints may fail with error code 1400
                // Invalid Window Handle.  Since Progman is the desktop no mapping is need.
                if ((IsProgmanWindow(hWndFrom) && hWndTo == IntPtr.Zero) ||
                    (hWndFrom == IntPtr.Zero && IsProgmanWindow(hWndTo))) 
                {
                    lastWin32Error = 0; 
                } 

                ThrowWin32ExceptionsIfError(lastWin32Error); 

                // If the coordinates is at the origin a zero return is valid.
                // Use GetLastError() to check that. Error code 0 is "Operation completed successfull".
                return lastWin32Error == 0; 
            }
 
            return true; 
        }
 
        // wrapper for MapWindowPoints
        internal static bool MapWindowPoints(IntPtr hWndFrom, IntPtr hWndTo, ref NativeMethods.Win32Point pt, int cPoints)
        {
            // The failure case of this API may also be a valid return.  GetLastError() is need to determine a true failure state. 
            // Clear the last error code to make sure we have a good starting condition to determine error state.
            UnsafeNativeMethods.SetLastError(0); 
            int mappingOffset = UnsafeNativeMethods.MapWindowPoints(hWndFrom, hWndTo, ref pt, cPoints); 
            int lastWin32Error = Marshal.GetLastWin32Error();
            if (mappingOffset == 0) 
            {
                // When mapping points to/from Progman and its children MapWindowPoints may fail with error code 1400
                // Invalid Window Handle.  Since Progman is the desktop no mapping is need.
                if ((IsProgmanWindow(hWndFrom) && hWndTo == IntPtr.Zero) || 
                    (hWndFrom == IntPtr.Zero && IsProgmanWindow(hWndTo)))
                { 
                    lastWin32Error = 0; 
                }
 
                ThrowWin32ExceptionsIfError(lastWin32Error);

                // If the coordinates is at the origin a zero return is valid.
                // Use GetLastError() to check that. Error code 0 is "Operation completed successfull". 
                return lastWin32Error == 0;
            } 
 
            return true;
        } 

        // Move the mouse to the x, y location and perfoms a mouse clik
        // The mouse is then brough back to the original location.
        internal static void MouseClick(int x, int y) 
        {
            MouseClick(x, y, false); 
        } 

        // Move the mouse to the x, y location and perfoms either 
        // a single of double clik depending on the fDoubleClick parameter
        // The mouse is then brough back to the original location.
        internal static void MouseClick(int x, int y, bool fDoubleClick)
        { 
            NativeMethods.Win32Point ptPrevious = new NativeMethods.Win32Point();
            bool fSetOldCursorPos = GetCursorPos(ref ptPrevious); 
            bool mouseSwapped = UnsafeNativeMethods.GetSystemMetrics(NativeMethods.SM_SWAPBUTTON) != 0; 

            Input.SendMouseInput(x, y, 0, SendMouseInputFlags.Move | SendMouseInputFlags.Absolute); 

            Input.SendMouseInput(0, 0, 0, mouseSwapped ? SendMouseInputFlags.RightDown : SendMouseInputFlags.LeftDown);
            Input.SendMouseInput(0, 0, 0, mouseSwapped ? SendMouseInputFlags.RightUp : SendMouseInputFlags.LeftUp);
 
            if (fDoubleClick)
            { 
                Input.SendMouseInput(0, 0, 0, mouseSwapped ? SendMouseInputFlags.RightDown : SendMouseInputFlags.LeftDown); 
                Input.SendMouseInput(0, 0, 0, mouseSwapped ? SendMouseInputFlags.RightUp : SendMouseInputFlags.LeftUp);
            } 

            // toolbar items don't have time to proccess the mouse click if we move it back too soon
            // so wait a small amount of time to give them a chance.  A value of 10 made this work
            // on a 2gig dual proc machine so 50 should cover a slower machine. 
            System.Threading.Thread.Sleep(50);
 
            // Set back the mouse position where it was 
            if (fSetOldCursorPos)
            { 
                Input.SendMouseInput(ptPrevious.x, ptPrevious.y, 0, SendMouseInputFlags.Move | SendMouseInputFlags.Absolute);
            }
        }
 
        [SecurityPermission(SecurityAction.Demand, UnmanagedCode = true)]
        internal static int MsgWaitForMultipleObjects(SafeWaitHandle handle, bool waitAll, int milliseconds, int wakeMask) 
        { 
            int terminationEvent, lastWin32Error;
            if (handle == null) 
            {
                terminationEvent = UnsafeNativeMethods.MsgWaitForMultipleObjects(0, null, waitAll, milliseconds, wakeMask);
                lastWin32Error = Marshal.GetLastWin32Error();
            } 
            else
            { 
                RuntimeHelpers.PrepareConstrainedRegions(); 
                bool fRelease = false;
                try 
                {
                    handle.DangerousAddRef(ref fRelease);
                    IntPtr[] handles = { handle.DangerousGetHandle() };
                    terminationEvent = UnsafeNativeMethods.MsgWaitForMultipleObjects(1, handles, waitAll, milliseconds, wakeMask); 
                    lastWin32Error = Marshal.GetLastWin32Error();
                } 
                finally 
                {
                    if (fRelease) 
                    {
                        handle.DangerousRelease();
                    }
                } 
            }
            if (terminationEvent == NativeMethods.WAIT_FAILED) 
            { 
                ThrowWin32ExceptionsIfError(lastWin32Error);
            } 
            return terminationEvent;
        }

        internal static IntPtr OpenProcess(int flags, bool inherit, uint processId, IntPtr hwnd) 
        {
            IntPtr processHandle = UnsafeNativeMethods.OpenProcess(flags, inherit, processId); 
            int lastWin32Error = Marshal.GetLastWin32Error(); 

            // If we fail due to permission issues, if we're on vista, try the hooking technique 
            // to access the process instead.
            if (processHandle == IntPtr.Zero
             && lastWin32Error == 5/*ERROR_ACCESS_DENIED*/
             && System.Environment.OSVersion.Version.Major >= 6) 
            {
                try 
                { 
                    processHandle = UnsafeNativeMethods.GetProcessHandleFromHwnd(hwnd);
                    lastWin32Error = Marshal.GetLastWin32Error(); 
                }
                catch(EntryPointNotFoundException)
                {
                    // Ignore; until OLEACC propogates into Vista builds, the entry point may not be present. 
                }
 
            } 

            if (processHandle == IntPtr.Zero) 
            {
                ThrowWin32ExceptionsIfError(lastWin32Error);
            }
 
            return processHandle;
        } 
 
        // wrapper for PostMessage
        internal static void PostMessage(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam) 
        {
            bool result = UnsafeNativeMethods.PostMessage(hwnd, msg, wParam, lParam);
            int lastWin32Error = Marshal.GetLastWin32Error();
            if (!result) 
            {
                ThrowWin32ExceptionsIfError(lastWin32Error); 
            } 
        }
 
        // Returns the Win32 Class Name for an hwnd
        internal static string ProxyGetClassName(IntPtr hwnd)
        {
            const int OBJID_QUERYCLASSNAMEIDX = unchecked(unchecked((int)0xFFFFFFF4)); 
            const int QUERYCLASSNAME_BASE = 65536;
 
            // Call ProxySendMessage ignoring the timeout 
            //
            int index = ProxySendMessageInt(hwnd, NativeMethods.WM_GETOBJECT, IntPtr.Zero, (IntPtr)OBJID_QUERYCLASSNAMEIDX, true); 

            if (index >= QUERYCLASSNAME_BASE && index - QUERYCLASSNAME_BASE < _asClassNames.Length)
            {
                return _asClassNames[index - QUERYCLASSNAME_BASE]; 
            }
            else 
            { 
                return  RealGetWindowClass(hwnd);
            } 
        }

        // wrapper for GetGuiThreadInfo
        internal static bool ProxyGetGUIThreadInfo(uint idThread, out NativeMethods.GUITHREADINFO gui) 
        {
            gui = new NativeMethods.GUITHREADINFO(); 
            gui.cbSize = Marshal.SizeOf(gui.GetType()); 

            bool result = UnsafeNativeMethods.GetGUIThreadInfo(idThread, ref gui); 
            int lastWin32Error = Marshal.GetLastWin32Error();

            if (!result)
            { 
                // If the focused thread is on another [secure] desktop, GetGUIThreadInfo
                // will fail with ERROR_ACCESS_DENIED - don't throw an exception for that case, 
                // instead treat as a failure. Callers will treat this as though no window has 
                // focus.
                if (lastWin32Error == 5 /*ERROR_ACCESS_DENIED*/) 
                    return false;

                ThrowWin32ExceptionsIfError(lastWin32Error);
            } 

#if _NEED_DEBUG_OUTPUT 
            bool fCaretBlink = (gui.dwFlags & NativeMethods.GUI_CARETBLINKING) != 0; 
            bool fMoveSize = (gui.dwFlags & NativeMethods.GUI_INMOVESIZE) != 0;
            bool fMenuMode = (gui.dwFlags & NativeMethods.GUI_INMENUMODE) != 0; 
            bool fSystemMenuMode = (gui.dwFlags & NativeMethods.GUI_SYSTEMMENUMODE) != 0;
            bool fPopupMenuMode = (gui.dwFlags & NativeMethods.GUI_POPUPMENUMODE) != 0;

            StringBuilder sbFlag = new StringBuilder(NativeMethods.MAX_PATH); 
            if (fCaretBlink)
            { 
                sbFlag.Append("GUI_CARETBLINKING"); 
            }
            if (fMoveSize) 
            {
                sbFlag.Append(sbFlag.Length > 0 ? " | GUI_INMOVESIZE" : "GUI_INMOVESIZE");
            }
            if (fMenuMode) 
            {
                sbFlag.Append(sbFlag.Length > 0 ? " | GUI_INMENUMODE" : "GUI_INMENUMODE"); 
            } 
            if (fSystemMenuMode)
            { 
                sbFlag.Append(sbFlag.Length > 0 ? " | GUI_SYSTEMMENUMODE" : "GUI_SYSTEMMENUMODE");
            }
            if (fPopupMenuMode)
            { 
                sbFlag.Append(sbFlag.Length > 0 ? " | GUI_POPUPMENUMODE" : "GUI_POPUPMENUMODE");
            } 
 
            StringBuilder sb = new StringBuilder(NativeMethods.MAX_PATH);
            sb.Append("GUITHREADINFO \n\r{"); 
            sb.AppendFormat("\n\r\tcbSize = {0}", gui.cbSize);
            sb.AppendFormat("\n\r\tdwFlags = {0}", gui.dwFlags);
            if (sbFlag.Length > 0)
            { 
                sb.Append(" (");
                sb.Append(sbFlag); 
                sb.Append(")"); 
            }
            sb.AppendFormat("\n\r\thwndActive = 0x{0:x8}", gui.hwndActive.ToInt32()); 
            sb.AppendFormat("\n\r\thwndFocus = 0x{0:x8}", gui.hwndFocus.ToInt32());
            sb.AppendFormat("\n\r\thwndCapture = 0x{0:x8}", gui.hwndCapture.ToInt32());
            sb.AppendFormat("\n\r\thwndMenuOwner = 0x{0:x8}", gui.hwndMenuOwner.ToInt32());
            sb.AppendFormat("\n\r\thwndMoveSize = 0x{0:x8}", gui.hwndMoveSize.ToInt32()); 
            sb.AppendFormat("\n\r\thwndCaret = 0x{0:x8}", gui.hwndCaret.ToInt32());
            sb.AppendFormat("\n\r\trc = ({0}, {1}, {2}, {3})", gui.rc.left, gui.rc.top, gui.rc.right, gui.rc.bottom); 
            sb.Append("\n\r}"); 

            System.Diagnostics.Debug.WriteLine(sb.ToString()); 
#endif

            return result;
        } 

        // The name text based on the WM_GETTEXT message. The text is truncated to a predefined character 
        // length. 
        internal static string ProxyGetText(IntPtr hwnd)
        { 
            return ProxyGetText(hwnd, MaxLengthNameProperty);
        }

        internal static string ProxyGetText(IntPtr hwnd, int length) 
        {
            // if the length is zero don't bother asking for the text. 
            if (length == 0) 
            {
                return ""; 
            }

            // Length passes to SendMessage includes terminating NUL
            StringBuilder str = new StringBuilder(length + 1); 

            // Send the message... 
            ProxySendMessage(hwnd, NativeMethods.WM_GETTEXT, (IntPtr)str.Capacity, str); 

            // We don't try to decifer between a zero length string and an error 
            return str.ToString();
        }

        // wrapper for GetTitleBarInfo 
        internal static bool ProxyGetTitleBarInfo(IntPtr hwnd, out UnsafeNativeMethods.TITLEBARINFO ti)
        { 
            ti = new UnsafeNativeMethods.TITLEBARINFO(); 
            ti.cbSize = Marshal.SizeOf(ti.GetType());
 
            bool result = UnsafeNativeMethods.GetTitleBarInfo(hwnd, ref ti);
            int lastWin32Error = Marshal.GetLastWin32Error();

            if (!result) 
            {
                ThrowWin32ExceptionsIfError(lastWin32Error); 
                return false; 
            }
            return true; 
        }

        internal static bool ProxyGetTitleBarInfoEx(IntPtr hwnd, out UnsafeNativeMethods.TITLEBARINFOEX ti)
        { 
            ti = new UnsafeNativeMethods.TITLEBARINFOEX();
            ti.cbSize = Marshal.SizeOf(ti.GetType()); 
            IntPtr result; 
            IntPtr resultSendMessage = UnsafeNativeMethods.SendMessageTimeout(hwnd, NativeMethods.WM_GETTITLEBARINFOEX, IntPtr.Zero, ref ti, _sendMessageFlags, _sendMessageTimeoutValue, out result);
            int lastWin32Error = Marshal.GetLastWin32Error(); 
            if (resultSendMessage == IntPtr.Zero)
            {
                //Window owner failed to process the message WM_GETTITLEBARINFOEX
                EvaluateSendMessageTimeoutError(lastWin32Error); 
            }
            return true; 
        } 

        // Return the bounding rects for titlebar items or null if they are invisible or offscreen 
        internal static Rect [] GetTitlebarRects(IntPtr hwnd)
        {
            // Vista and beyond
            if (System.Environment.OSVersion.Version.Major >= 6) 
            {
                return GetTitlebarRectsEx(hwnd); 
            } 

            // Up through XP 
            return GetTitlebarRectsXP(hwnd);
        }

        internal static Rect GetTitleBarRect(IntPtr hwnd) 
        {
            UnsafeNativeMethods.TITLEBARINFO ti; 
            if (!Misc.ProxyGetTitleBarInfo(hwnd, out ti) || ti.rcTitleBar.IsEmpty) 
            {
                return Rect.Empty; 
            }

            NativeMethods.MENUBARINFO mbi;
            bool retValue = WindowsMenu.GetMenuBarInfo(hwnd, NativeMethods.OBJID_SYSMENU, 0, out mbi); 

            // Possible that there is no menu 
            int left = (!retValue || mbi.rcBar.IsEmpty) ? ti.rcTitleBar.left : mbi.rcBar.left; 
            return new Rect(left, ti.rcTitleBar.top, ti.rcTitleBar.right - left, ti.rcTitleBar.bottom - ti.rcTitleBar.top);
        } 

        internal static IntPtr ProxySendMessage(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam)
        {
            IntPtr result; 

            IntPtr resultSendMessage = UnsafeNativeMethods.SendMessageTimeout(hwnd, msg, wParam, lParam, _sendMessageFlags, _sendMessageTimeoutValue, out result); 
            int lastWin32Error = Marshal.GetLastWin32Error(); 

            if (resultSendMessage == IntPtr.Zero) 
            {
                EvaluateSendMessageTimeoutError(lastWin32Error);
            }
 
            return result;
        } 
 
        // On a 64-bit platform, the value of the IntPtr is too large to represent as a 32-bit signed integer.
        // An int is a System.Int32.  When an explicit cast of IntPtr to int is done on a 64-bit platform an 
        // OverflowException will occur when the IntPtr value exceeds the range of int. In cases where using
        // SendMessage to get back int (e.g. an item index or an enum value), this version safely truncates
        // from IntPtr to int.
        internal static int ProxySendMessageInt(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam) 
        {
            IntPtr result = ProxySendMessage(hwnd, msg, wParam, lParam); 
            return unchecked((int)(long)result); 
        }
 
        // Same as above but does not throw on timeout
        // @
        internal static IntPtr ProxySendMessage(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, bool ignoreTimeout)
        { 
            IntPtr result;
 
            IntPtr resultSendMessage = UnsafeNativeMethods.SendMessageTimeout(hwnd, msg, wParam, lParam, _sendMessageFlags, _sendMessageTimeoutValue, out result); 
            int lastWin32Error = Marshal.GetLastWin32Error();
 
            if (resultSendMessage == IntPtr.Zero)
            {
                EvaluateSendMessageTimeoutError(lastWin32Error, ignoreTimeout);
            } 

            return result; 
        } 

        // On a 64-bit platform, the value of the IntPtr is too large to represent as a 32-bit signed integer. 
        // An int is a System.Int32.  When an explicit cast of IntPtr to int is done on a 64-bit platform an
        // OverflowException will occur when the IntPtr value exceeds the range of int. In cases where using
        // SendMessage to get back int (e.g. an item index or an enum value), this version safely truncates
        // from IntPtr to int. 
        internal static int ProxySendMessageInt(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, bool ignoreTimeout)
        { 
            IntPtr result = ProxySendMessage(hwnd, msg, wParam, lParam, ignoreTimeout); 
            return unchecked((int)(long)result);
        } 

        internal static IntPtr ProxySendMessage(IntPtr hwnd, int msg, IntPtr wParam, StringBuilder sb)
        {
            IntPtr result; 

            IntPtr resultSendMessage = UnsafeNativeMethods.SendMessageTimeout(hwnd, msg, wParam, sb, _sendMessageFlags, _sendMessageTimeoutValue, out result); 
            int lastWin32Error = Marshal.GetLastWin32Error(); 

            if (resultSendMessage == IntPtr.Zero) 
            {
                EvaluateSendMessageTimeoutError(lastWin32Error);
            }
 
            return result;
        } 
 
        // On a 64-bit platform, the value of the IntPtr is too large to represent as a 32-bit signed integer.
        // An int is a System.Int32.  When an explicit cast of IntPtr to int is done on a 64-bit platform an 
        // OverflowException will occur when the IntPtr value exceeds the range of int. In cases where using
        // SendMessage to get back int (e.g. an item index or an enum value), this version safely truncates
        // from IntPtr to int.
        internal static int ProxySendMessageInt(IntPtr hwnd, int msg, IntPtr wParam, StringBuilder sb) 
        {
            IntPtr result = ProxySendMessage(hwnd, msg, wParam, sb); 
            return unchecked((int)(long)result); 
        }
 
        internal static IntPtr ProxySendMessage(IntPtr hwnd, int msg, IntPtr wParam, ref NativeMethods.Win32Rect lParam)
        {
            IntPtr result;
 
            IntPtr resultSendMessage = UnsafeNativeMethods.SendMessageTimeout(hwnd, msg, wParam, ref lParam, _sendMessageFlags, _sendMessageTimeoutValue, out result);
            int lastWin32Error = Marshal.GetLastWin32Error(); 
 
            if (resultSendMessage == IntPtr.Zero)
            { 
                EvaluateSendMessageTimeoutError(lastWin32Error);
            }

            return result; 
        }
 
        internal static IntPtr ProxySendMessage(IntPtr hwnd, int msg, out int wParam, out int lParam) 
        {
            IntPtr result; 

            IntPtr resultSendMessage = UnsafeNativeMethods.SendMessageTimeout(hwnd, msg, out wParam, out lParam, _sendMessageFlags, _sendMessageTimeoutValue, out result);
            int lastWin32Error = Marshal.GetLastWin32Error();
 
            if (resultSendMessage == IntPtr.Zero)
            { 
                EvaluateSendMessageTimeoutError(lastWin32Error); 
            }
 
            return result;
        }

        // Check if a point is within the bounding Rect of a window 
        internal static bool PtInRect(ref NativeMethods.Win32Rect rc, int x, int y)
        { 
            return x >= rc.left && x < rc.right && y >= rc.top && y < rc.bottom; 
        }
 
        internal static bool PtInRect(ref Rect rc, int x, int y)
        {
            return x >= rc.Left && x < rc.Right && y >= rc.Top && y < rc.Bottom;
        } 

        // Check if a point is within the client Rect of a window 
        internal static bool PtInWindowRect(IntPtr hwnd, int x, int y) 
        {
            NativeMethods.Win32Rect rc = new NativeMethods.Win32Rect(); 

            if (!GetWindowRect(hwnd, ref rc))
            {
                return false; 
            }
            return x >= rc.left && x < rc.right && y >= rc.top && y < rc.bottom; 
        } 

        internal static bool ReadProcessMemory(MS.Internal.AutomationProxies.SafeProcessHandle hProcess, IntPtr source, IntPtr dest, IntPtr size, out int bytesRead) 
        {
            bool result = UnsafeNativeMethods.ReadProcessMemory(hProcess, source, dest, size, out bytesRead);
            int lastWin32Error = Marshal.GetLastWin32Error();
 
            if (!result)
            { 
                ThrowWin32ExceptionsIfError(lastWin32Error); 
            }
 
            return result;
        }

        internal static bool ReadProcessMemory(MS.Internal.AutomationProxies.SafeProcessHandle hProcess, IntPtr source, MS.Internal.AutomationProxies.SafeCoTaskMem destAddress, IntPtr size, out int bytesRead) 
        {
            bool result = UnsafeNativeMethods.ReadProcessMemory(hProcess, source, destAddress, size, out bytesRead); 
            int lastWin32Error = Marshal.GetLastWin32Error(); 

            if (!result) 
            {
                ThrowWin32ExceptionsIfError(lastWin32Error);
            }
 
            return result;
        } 
 
        // Get the class name
        internal static string RealGetWindowClass(IntPtr hwnd) 
        {
            System.Text.StringBuilder className = new System.Text.StringBuilder(NativeMethods.MAX_PATH + 1);

            uint result = UnsafeNativeMethods.RealGetWindowClass(hwnd, className, NativeMethods.MAX_PATH); 
            int lastWin32Error = Marshal.GetLastWin32Error();
 
            if (result == 0) 
            {
                ThrowWin32ExceptionsIfError(lastWin32Error); 
                return "";
            }

            return className.ToString(); 
        }
 
        internal static bool RegisterHotKey(IntPtr hwnd, short atom, int modifiers, int vk) 
        {
            bool result = UnsafeNativeMethods.RegisterHotKey(hwnd, atom, modifiers, vk); 
            int lastWin32Error = Marshal.GetLastWin32Error();

            if (!result)
            { 
                ThrowWin32ExceptionsIfError(lastWin32Error);
            } 
 
            return result;
        } 

        internal static int ReleaseDC(IntPtr hwnd, IntPtr hdc)
        {
            // If ReleaseDC fails we will not do anything with that information so just ignore the 
            // PRESHARP warnings.
#pragma warning suppress 6031, 6523 
            return UnsafeNativeMethods.ReleaseDC(hwnd, hdc); 
        }
 
        internal static int RegisterWindowMessage(string msg)
        {
            int result = SafeNativeMethods.RegisterWindowMessage(msg);
            int lastWin32Error = Marshal.GetLastWin32Error(); 

            if (result == 0) 
            { 
                ThrowWin32ExceptionsIfError(lastWin32Error);
            } 

            return result;
        }
 
        internal static IntPtr SelectObject(IntPtr hdc, IntPtr hObject)
        { 
            // There is no indication in the Windows SDK documentation that SelectObject() 
            // will set an error to be retrieved with GetLastError, so set the pragma to ignore
            // the PRESHARP warning.  Anyway if ReleaseDC() fails here, nothing more can be done 
            // since the code is restoring the orginal object and discarding the temp object.
#pragma warning suppress 6031, 6523
            return UnsafeNativeMethods.SelectObject(hdc, hObject);
        } 

        internal static int SendInput(int inputs, ref NativeMethods.INPUT ki, int size) 
        { 
            int eventCount = UnsafeNativeMethods.SendInput(inputs, ref ki, size);
            int lastWin32Error = Marshal.GetLastWin32Error(); 

            if (eventCount <= 0)
            {
                ThrowWin32ExceptionsIfError(lastWin32Error); 
            }
 
            return eventCount; 
        }
 
        // The Win32 call to SetFocus does not do it for hwnd that are
        // not in the same process as the caller.
        // This is implemented here to work around this behavior.
        // Fake keystroke are sent to a specific hwnd to force 
        // Windows to give the focus to that hwnd.
        static internal bool SetFocus(IntPtr hwnd) 
        { 
            // First Check for ComboLBox
            // Because it uses Keystrokes it dismisses the ComboLBox 
            string className = RealGetWindowClass(hwnd);

            if (className == "ComboLBox")
                return true; 

 
            // If window is currently Disabled or Invisible no need 
            // to continue
            if (!SafeNativeMethods.IsWindowVisible(hwnd) || !SafeNativeMethods.IsWindowEnabled(hwnd)) 
            {
                return false;
            }
 
            // If already focused, leave as-is. Calling SetForegroundWindow
            // on an already focused HWND will remove focus! 
            if (GetFocusedWindow().Equals(hwnd)) 
            {
                return true; 
            }

            // Try calling SetForegroundWindow directly first; it should succeed if we
            // already have the focus or have UIAccess 
            if (UnsafeNativeMethods.SetForegroundWindow(hwnd))
            { 
                return true; 
            }
 
            // Use the hotkey technique:
            // Register a hotkey and send it to ourselves - this gives us the
            // input, and allows us to call SetForegroundWindow.
            short atom = GlobalAddAtom("FocusHotKey"); 
            if (atom == 0)
            { 
                return false; 
            }
            short vk = 0xB9; 
            bool gotHotkey = false;

            for (int tries = 0; tries < 10; tries++)
            { 
                if (RegisterHotKey(IntPtr.Zero, atom, 0, vk))
                { 
                    gotHotkey = true; 
                    break;
                } 

                vk++; // try another key
            }
 
            if (gotHotkey)
            { 
                // Get state of modifiers - and temporarilly release them... 
                bool fShiftDown = (UnsafeNativeMethods.GetAsyncKeyState(UnsafeNativeMethods.VK_SHIFT) & unchecked((int)0x80000000)) != 0;
                bool fAltDown = (UnsafeNativeMethods.GetAsyncKeyState(UnsafeNativeMethods.VK_MENU) & unchecked((int)0x80000000)) != 0; 
                bool fCtrlDown = (UnsafeNativeMethods.GetAsyncKeyState(UnsafeNativeMethods.VK_CONTROL) & unchecked((int)0x80000000)) != 0;

                if (fShiftDown)
                    Input.SendKeyboardInputVK(UnsafeNativeMethods.VK_SHIFT, false); 

                if (fAltDown) 
                    Input.SendKeyboardInputVK(UnsafeNativeMethods.VK_MENU, false); 

                if (fCtrlDown) 
                    Input.SendKeyboardInputVK(UnsafeNativeMethods.VK_CONTROL, false);

                Input.SendKeyboardInputVK(vk, true);
                Input.SendKeyboardInputVK(vk, false); 

                // Restore release modifier keys... 
                if (fShiftDown) 
                    Input.SendKeyboardInputVK(UnsafeNativeMethods.VK_SHIFT, true);
 
                if (fAltDown)
                    Input.SendKeyboardInputVK(UnsafeNativeMethods.VK_MENU, true);

                if (fCtrlDown) 
                    Input.SendKeyboardInputVK(UnsafeNativeMethods.VK_CONTROL, true);
 
                // Spin in this message loop until we get the hot key 
                while (true)
                { 
                    // If the hotkey input gets lost (eg due to desktop switch), GetMessage may not return -
                    // so use MsgWait first so we can timeout if there's no message present instead of blocking.
                    int result = MsgWaitForMultipleObjects(null, false, 2000, NativeMethods.QS_ALLINPUT);
                    if (result == NativeMethods.WAIT_FAILED || result == NativeMethods.WAIT_TIMEOUT) 
                        break;
 
                    NativeMethods.MSG msg = new NativeMethods.MSG(); 
                    if (!GetMessage(ref msg, IntPtr.Zero, 0, 0))
                        break; 

                    // TranslateMessage() will not set an error to be retrieved with GetLastError,
                    // so set the pragma to ignore the PERSHARP warning.
                    // the PERSHARP warning. 
#pragma warning suppress 6031, 6523
                    UnsafeNativeMethods.TranslateMessage(ref msg); 
 
                    // From the Windows SDK documentation:
                    // The return value specifies the value returned by the window procedure. 
                    // Although its meaning depends on the message being dispatched, the return
                    // value generally is ignored.
#pragma warning suppress 6031, 6523
                    UnsafeNativeMethods.DispatchMessage(ref msg); 

                    if (msg.message == NativeMethods.WM_HOTKEY && (short)msg.wParam == atom) 
                    { 
                        break;
                    } 
                }

                UnregisterHotKey(IntPtr.Zero, atom);
            } 

            GlobalDeleteAtom(atom); 
 
            return UnsafeNativeMethods.SetForegroundWindow(hwnd);
        } 

        internal static int SetScrollPos(IntPtr hwnd, int bar, int pos, bool redraw)
        {
            // NOTE: From Windows SDK Documentaion: 
            // If the function succeeds, the return value is the previous position of the scroll
            // box.  If the desktop is themed and the parent window is a message-only window, 
            // the function returns an incorrect value. 

            // The failure case of this API may also be a valid return.  GetLastError() is need to determine a true failure state. 
            // Clear the last error code to make sure we have a good starting condition to determine error state.
            UnsafeNativeMethods.SetLastError(0);
            int prevPos = UnsafeNativeMethods.SetScrollPos(hwnd, bar, pos, redraw);
            int lastWin32Error = Marshal.GetLastWin32Error(); 

            if (prevPos == 0) 
            { 
                ThrowWin32ExceptionsIfError(lastWin32Error);
            } 

            return prevPos;
        }
 
        internal static IntPtr SetWinEventHook(int eventMin, int eventMax, IntPtr hmodWinEventProc, NativeMethods.WinEventProcDef WinEventReentrancyFilter, uint idProcess, uint idThread, int dwFlags)
        { 
            // There is no indication in the Windows SDK documentation that SetWinEventHook() 
            // will set an error to be retrieved with GetLastError, so set the pragma to ignore
            // the PERSHARP warning. 
#pragma warning suppress 6523
            return UnsafeNativeMethods.SetWinEventHook(eventMin, eventMax, hmodWinEventProc, WinEventReentrancyFilter, idProcess, idThread, dwFlags);
        }
 
        // this strips the mnemonic prefix for short cuts as well as leading spaces
        // If we find && leave one & there. 
        internal static string StripMnemonic(string s) 
        {
            // If there are no spaces or & then it's ok just return it 
            if (string.IsNullOrEmpty(s) || s.IndexOfAny(new char[2] { ' ', '&' }) < 0)
            {
                return s;
            } 

            char[] ach = s.ToCharArray(); 
            bool amper = false; 
            bool leadingSpace = false;
            int dest = 0; 

            for (int source = 0; source < ach.Length; source++)
            {
                // get rid of leading spaces 
                if (ach[source] == ' ' && leadingSpace == false)
                { 
                    continue; 
                }
                else 
                {
                    leadingSpace = true;
                }
 
                // get rid of &
                if (ach[source] == '&' && amper == false) 
                { 
                    amper = true;
                } 
                else
                {
                    ach[dest++] = ach[source];
                } 
            }
 
            return new string(ach, 0, dest); 
        }
 
        internal static void ThrowWin32ExceptionsIfError(int errorCode)
        {
            switch (errorCode)
            { 
                case 0:     //    0 ERROR_SUCCESS                   The operation completed successfully.
                    // The error code indicates that there is no error, so do not throw an exception. 
                    break; 

                case 6:     //    6 ERROR_INVALID_HANDLE            The handle is invalid. 
                case 1400:  // 1400 ERROR_INVALID_WINDOW_HANDLE     Invalid window handle.
                case 1401:  // 1401 ERROR_INVALID_MENU_HANDLE       Invalid menu handle.
                case 1402:  // 1402 ERROR_INVALID_CURSOR_HANDLE     Invalid cursor handle.
                case 1403:  // 1403 ERROR_INVALID_ACCEL_HANDLE      Invalid accelerator table handle. 
                case 1404:  // 1404 ERROR_INVALID_HOOK_HANDLE       Invalid hook handle.
                case 1405:  // 1405 ERROR_INVALID_DWP_HANDLE        Invalid handle to a multiple-window position structure. 
                case 1406:  // 1406 ERROR_TLW_WITH_WSCHILD          Cannot create a top-level child window. 
                case 1407:  // 1407 ERROR_CANNOT_FIND_WND_CLASS     Cannot find window class.
                case 1408:  // 1408 ERROR_WINDOW_OF_OTHER_THREAD    Invalid window; it belongs to other thread. 
                    throw new ElementNotAvailableException();

                // We're getting this in AMD64 when calling RealGetWindowClass; adding this code
                // to allow the DRTs to pass while we continue investigation. 
                case 87:    //   87 ERROR_INVALID_PARAMETER
                    throw new ElementNotAvailableException(); 
 
                case 8:     //    8 ERROR_NOT_ENOUGH_MEMORY         Not enough storage is available to process this command.
                case 14:    //   14 ERROR_OUTOFMEMORY               Not enough storage is available to complete this operation. 
                    throw new OutOfMemoryException();

                case 998:   //  998 ERROR_NOACCESS                  Invalid access to memory location.
                case 5:     //    5 ERROR_ACCESS_DENIED 
                    throw new InvalidOperationException();
 
                case 121:   //  121 ERROR_SEM_TIMEOUT               The semaphore timeout period has expired. 
                case 258:   //  258 WAIT_TIMEOUT                    The wait operation timed out.
                case 1053:  // 1053 ERROR_SERVICE_REQUEST_TIMEOUT   The service did not respond to the start or control request in a timely fashion. 
                case 1460:  // 1460 ERROR_TIMEOUT                   This operation returned because the timeout period expired.
                    throw new TimeoutException();

                default: 
                    // Not sure how to map the reset of the error codes so throw generic Win32Exception.
                    throw new Win32Exception(errorCode); 
            } 
        }
 
        internal static bool UnhookWinEvent(IntPtr winEventHook)
        {
            // There is no indication in the Windows SDK documentation that UnhookWinEvent()
            // will set an error to be retrieved with GetLastError, so set the pragma to ignore 
            // the PERSHARP warning.
#pragma warning suppress 6523 
            return UnsafeNativeMethods.UnhookWinEvent(winEventHook); 
        }
 
        internal static bool UnionRect(out NativeMethods.Win32Rect rcDst, ref NativeMethods.Win32Rect rc1, ref NativeMethods.Win32Rect rc2)
        {
            bool result = SafeNativeMethods.UnionRect(out rcDst, ref rc1, ref rc2);
            int lastWin32Error = Marshal.GetLastWin32Error(); 

            if (!result) 
            { 
                ThrowWin32ExceptionsIfError(lastWin32Error);
            } 

            return result;
        }
 
        internal static bool UnregisterHotKey(IntPtr hwnd, short atom)
        { 
            bool result = UnsafeNativeMethods.UnregisterHotKey(hwnd, atom); 
            int lastWin32Error = Marshal.GetLastWin32Error();
 
            if (!result)
            {
                ThrowWin32ExceptionsIfError(lastWin32Error);
            } 

            return result; 
        } 

        internal static IntPtr VirtualAlloc(IntPtr address, UIntPtr size, int allocationType, int protect) 
        {
            IntPtr result = UnsafeNativeMethods.VirtualAlloc(address, size, allocationType, protect);
            int lastWin32Error = Marshal.GetLastWin32Error();
 
            if (result == IntPtr.Zero)
            { 
                ThrowWin32ExceptionsIfError(lastWin32Error); 
            }
 
            return result;
        }

        internal static IntPtr VirtualAllocEx(MS.Internal.AutomationProxies.SafeProcessHandle hProcess, IntPtr address, UIntPtr size, int allocationType, int protect) 
        {
            IntPtr result = UnsafeNativeMethods.VirtualAllocEx(hProcess, address, size, allocationType, protect); 
            int lastWin32Error = Marshal.GetLastWin32Error(); 

            if (result == IntPtr.Zero) 
            {
                ThrowWin32ExceptionsIfError(lastWin32Error);
            }
 
            return result;
        } 
 
        internal static bool VirtualFree(IntPtr address, UIntPtr size, int freeType)
        { 
            bool result = UnsafeNativeMethods.VirtualFree(address, size, freeType);
            int lastWin32Error = Marshal.GetLastWin32Error();

            if (!result) 
            {
                ThrowWin32ExceptionsIfError(lastWin32Error); 
            } 

            return result; 
        }

        internal static bool VirtualFreeEx(MS.Internal.AutomationProxies.SafeProcessHandle hProcess, IntPtr address, UIntPtr size, int freeType)
        { 
            bool result = UnsafeNativeMethods.VirtualFreeEx(hProcess, address, size, freeType);
            int lastWin32Error = Marshal.GetLastWin32Error(); 
 
            if (!result)
            { 
                ThrowWin32ExceptionsIfError(lastWin32Error);
            }

            return result; 
        }
 
        internal static bool WriteProcessMemory(MS.Internal.AutomationProxies.SafeProcessHandle hProcess, IntPtr dest, IntPtr sourceAddress, IntPtr size, out int bytesWritten) 
        {
            bool result = UnsafeNativeMethods.WriteProcessMemory(hProcess, dest, sourceAddress, size, out bytesWritten); 
            int lastWin32Error = Marshal.GetLastWin32Error();

            if (!result)
            { 
                ThrowWin32ExceptionsIfError(lastWin32Error);
            } 
 
            return result;
        } 

        internal static bool IsWindowInGivenProcess(IntPtr hwnd, string targetprocess)
        {
            uint processId; 
            //GetWindowThreadProcessId throws ElementNotAvailableException if the hwnd is no longer valid.
            //But, this exception should be handled by the client accessing this proxy. 
            uint threadId = GetWindowThreadProcessId(hwnd, out processId); 
            try
            { 
                string processName = System.Diagnostics.Process.GetProcessById((int)processId).ProcessName;
                if (processName == targetprocess)
                {
                    return true; 
                }
            } 
            catch (Exception ex) 
            {
                if (IsCriticalException(ex)) 
                    throw;

                if (ex is ArgumentException || ex is SystemException)
                { 
                    //The process is no longer running which implies AutomationElement is no longer available.
                    //Let the client handle it. 
                    throw new ElementNotAvailableException(); 
                }
 
                //All other exceptions are ignored as the purpose of this method is to find whether the hwnd belongs to
                //a particular process or not.
            }
            return false; 
        }
 
        internal static bool InTheShellProcess(IntPtr hwnd) 
        {
            IntPtr hwndShell = SafeNativeMethods.GetShellWindow(); 
            if (hwndShell == IntPtr.Zero)
                return false;
            uint idProcessUs;
            GetWindowThreadProcessId(hwnd, out idProcessUs); 
            uint idProcessShell;
            GetWindowThreadProcessId(hwndShell, out idProcessShell); 
            return idProcessUs == idProcessShell; 
        }
 
        // the windows listview has feature (like group by) in v6 that only exist on
        // vista and beyond.  This lets us test for that.
        internal static bool IsComctrlV6OnOsVerV6orHigher(IntPtr hwnd)
        { 
            int commonControlVersion  = Misc.ProxySendMessageInt(hwnd, NativeMethods.CCM_GETVERSION, IntPtr.Zero, IntPtr.Zero);
            if (Environment.OSVersion.Version.Major >= 6 && commonControlVersion >= 6) 
            { 
                return true;
            } 

            return false;
        }
 
        #endregion
 
        // ------------------------------------------------------ 
        //
        // Internal Fields 
        //
        // ------------------------------------------------------

        #region Internal Fields 

        // Max length for the name 
        internal const int MaxLengthNameProperty = 2000; 

        // Timeout for clearing menus 
        internal const long MenuTimeOut = 100;

        #endregion
 
        // -----------------------------------------------------
        // 
        // Private Methods 
        //
        // ------------------------------------------------------ 

        #region Private Methods

        private static bool EnumToolTipWindows(IntPtr hwnd, ref UnsafeNativeMethods.ENUMTOOLTIPWINDOWINFO lParam) 
        {
            // Use ProxyGetClassName here instead of GetClassName(), 
            // since for a winforms tooltip the latter will return 
            // "WindowsForms10.tooltips_class32.app.0.b7ab7b".
            // Instead, ProxyGetClassName uses WM_GETOBJECT with 
            // OBJID_QUERYCLASSNAMEIDX, which will return the correct answer.
            if (!ProxyGetClassName(hwnd).Equals("tooltips_class32"))
            {
                return true; 
            }
 
            NativeMethods.TOOLINFO tool = new NativeMethods.TOOLINFO(); 
            tool.Init(Marshal.SizeOf(typeof(NativeMethods.TOOLINFO)));
            // For tooltips with ids of 0, MFC will create the tooltip with the flag of TTF_IDISHWND. 
            // TTF_IDISHWND indicates that the uId member is the window handle to the tool.
            if (lParam.id == 0)
            {
                tool.hwnd = Misc.GetParent(lParam.hwnd); 
                tool.uId = unchecked((int)lParam.hwnd);
                tool.uFlags = NativeMethods.TTF_IDISHWND; 
            } 
            else
            { 
                tool.hwnd = lParam.hwnd;
                tool.uId = lParam.id;
            }
 
            string name = XSendMessage.GetItemText(hwnd, tool);
 
            // Didn't get anything - continue looking... 
            if (string.IsNullOrEmpty(name))
            { 
                return true;
            }

            lParam.name = name; 

            // Got it - can stop iterating now. 
            return false; 
        }
 
        // Get the size of a page in memory for VirtualAlloc
        private static uint GetPageSize()
        {
            NativeMethods.SYSTEM_INFO sysInfo; 
            UnsafeNativeMethods.GetSystemInfo(out sysInfo);
            return sysInfo.dwPageSize; 
        } 

        //This function throws corresponding exception depending on the last error. 
        private static void EvaluateSendMessageTimeoutError(int error)
        {
            EvaluateSendMessageTimeoutError(error, false);
        } 

        private static void EvaluateSendMessageTimeoutError(int error, bool ignoreTimeout) 
        { 
            // SendMessageTimeout Function
            // If the function fails or times out, the return value is zero. To get extended error information, 
            // call GetLastError. If GetLastError returns zero, then the function timed out.
            // NOTE: The GetLastError after a SendMessageTimeout my also be an ERROR_TIMEOUT depending on the
            // message.
 
            // 1460 This operation returned because the timeout period expired. ERROR_TIMEOUT
            if (error == 0 || error == 1460) 
            { 
                if (!ignoreTimeout)
                { 
                    throw new TimeoutException();
                }
            }
            else 
            {
                ThrowWin32ExceptionsIfError(error); 
            } 
        }
 
        private static Rect[] GetTitlebarRectsXP(IntPtr hwnd)
        {
            Debug.Assert(System.Environment.OSVersion.Version.Major < 6);
 
            UnsafeNativeMethods.TITLEBARINFO tiDL;
            if (!Misc.ProxyGetTitleBarInfo(hwnd, out tiDL)) 
            { 
                return null;
            } 

            // Titlebars that are invisible or may not exist should not have a rect
            if ((tiDL.rgstate[NativeMethods.INDEX_TITLEBAR_SELF] & (NativeMethods.STATE_SYSTEM_INVISIBLE | NativeMethods.STATE_SYSTEM_OFFSCREEN)) != 0)
            { 
                return null;
            } 
 
            // We really should be using the the theme APIs but they give incorrect results with the titlebar buttons so we are reverting back to system metrics
            // This is not perfect, its a looks like it may be a few pixels of here or there but clicking on the center of the button will be sucessfull.  The only place this 
            // does not work is on console windows when the theme is Windows Clasic Style.

            // The system metric seems to be just bit off, subtracting 1 seems to get a better result on all themes
            int buttonWidth = UnsafeNativeMethods.GetSystemMetrics(NativeMethods.SM_CXSIZE) - 1; 
            int buttonHeight = UnsafeNativeMethods.GetSystemMetrics(NativeMethods.SM_CYSIZE) - 1;
 
            Rect[] rects = new Rect[NativeMethods.CCHILDREN_TITLEBAR + 1]; 

            // Start at the end and work backwards to the system menu.  Subtract buttonSize when a child is present. 
            int leftEdge;

            if (Misc.IsLayoutRTL(hwnd))
            { 
                // Right to left mirroring style
 
                // This is to take in count for a bug in GetTitleBarInfo().  It does not calculate the 
                // rcTitleBar correctly when the WS_EX_LAYOUTRTL extended style is set.  It assumes
                // SYSMENU is always on the left and removes its space from the wrong side of rcTitleBar. 
                // Use the bounding rectangle of the whole title bar to get the true left boundary.
                leftEdge = (int)(Misc.GetTitleBarRect(hwnd).Left);
                for (int i = NativeMethods.INDEX_TITLEBAR_MAC; i > NativeMethods.INDEX_TITLEBAR_SELF; i--)
                { 
                    if ((tiDL.rgstate[i] & NativeMethods.STATE_SYSTEM_INVISIBLE) == 0)
                    { 
                        rects[i] = new Rect(leftEdge, tiDL.rcTitleBar.top, buttonWidth, buttonHeight); 
                        leftEdge += buttonWidth;
                    } 
                    else
                    {
                        rects[i] = Rect.Empty;
                    } 
                }
            } 
            else 
            {
                leftEdge = tiDL.rcTitleBar.right - buttonWidth; 
                for (int i = NativeMethods.INDEX_TITLEBAR_MAC; i > NativeMethods.INDEX_TITLEBAR_SELF; i--)
                {
                    if ((tiDL.rgstate[i] & NativeMethods.STATE_SYSTEM_INVISIBLE) == 0)
                    { 
                        rects[i] = new Rect(leftEdge, tiDL.rcTitleBar.top, buttonWidth, buttonHeight);
                        leftEdge -= buttonWidth; 
                    } 
                    else
                    { 
                        rects[i] = Rect.Empty;
                    }
                }
            } 

            return rects; 
        } 

        private static Rect[] GetTitlebarRectsEx(IntPtr hwnd) 
        {
            Debug.Assert(System.Environment.OSVersion.Version.Major >= 6);

            UnsafeNativeMethods.TITLEBARINFOEX ti; 
            if (!Misc.ProxyGetTitleBarInfoEx(hwnd, out ti))
            { 
                return null; 
            }
 
            // Titlebars that are invisible or may not exist should not have a rect
            if ((ti.rgstate[NativeMethods.INDEX_TITLEBAR_SELF] & (NativeMethods.STATE_SYSTEM_INVISIBLE | NativeMethods.STATE_SYSTEM_OFFSCREEN)) != 0)
            {
                return null; 
            }
 
            Rect[] rects = new Rect[NativeMethods.CCHILDREN_TITLEBAR + 1]; 
            for (int i = 0; i <= NativeMethods.CCHILDREN_TITLEBAR; i++)
            { 
                // Buttons that are invisible or may not exist should not have a rect
                if ((ti.rgstate[i] & NativeMethods.STATE_SYSTEM_INVISIBLE) != 0)
                {
                    rects[i] = Rect.Empty; 
                }
                else 
                { 
                    rects[i] = new Rect(ti.rgrect[i].left, ti.rgrect[i].top, ti.rgrect[i].right - ti.rgrect[i].left, ti.rgrect[i].bottom - ti.rgrect[i].top);
                } 
            }

            return rects;
        } 

        #endregion 
 
        // -----------------------------------------------------
        // 
        // Private Fields
        //
        // -----------------------------------------------------
 
        #region Private Fields
 
        // Generic flags for SendMessages 
        private const int _sendMessageFlags = NativeMethods.SMTO_BLOCK;
 
        // Generic time out for SendMessages
        // Most messages won't need anything near this - but there are a few - eg. WM_COMMAND/CBN_DROPDOWN
        // when sent to IE's address combo for the first time causes it to populate iself, and that can
        // take a couple of seconds on a slow machine. 
        private const int _sendMessageTimeoutValue = 10000;
 
        // Array of known class names 
        private static string[] _asClassNames = {
            "ListBox", 
            "#32768",
            "Button",
            "Static",
            "Edit", 
            "ComboBox",
            "#32770", 
            "#32771", 
            "MDIClient",
            "#32769", 
            "ScrollBar",
            "msctls_statusbar32",
            "ToolbarWindow32",
            "msctls_progress32", 
            "SysAnimate32",
            "SysTabControl32", 
            "msctls_hotkey32", 
            "SysHeader32",
            "msctls_trackbar32", 
            "SysListView32",
            "OpenListView",
            "msctls_updown",
            "msctls_updown32", 
            "tooltips_class",
            "tooltips_class32", 
            "SysTreeView32", 
            "SysMonthCal32",
            "SysDateTimePick32", 
            "RICHEDIT",
            "RichEdit20A",
            "RichEdit20W",
            "SysIPAddress32" 
        };
 
        #endregion 

    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
//---------------------------------------------------------------------------- 
//
// 
//    Copyright (C) Microsoft Corporation.  All rights reserved.
//  
//
// 
// Description: Miscellaneous helper routines 
//
// History: 
//  12/06/2004 : Created [....]
//
//---------------------------------------------------------------------------
 

// PRESHARP: In order to avoid generating warnings about unkown message numbers and unknown pragmas. 
#pragma warning disable 1634, 1691 

using Microsoft.Win32.SafeHandles; 
using MS.Win32;
using System;
using System.Collections;
using System.ComponentModel; 
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; 
using System.Security.Permissions; 
using System.Text;
using System.Windows.Automation; 
using System.Windows.Automation.Provider;
using System.Windows;
using System.Windows.Input;
using System.Diagnostics; 

namespace MS.Internal.AutomationProxies 
{ 
    static class Misc
    { 

        //-----------------------------------------------------
        //
        //  Internal Methods 
        //
        //----------------------------------------------------- 
 
        #region Internal Methods
 
        //
        //  HrGetWindowShortcut()
        //
        internal static string AccessKey(string s) 
        {
            // Get the index of the shortcut 
            int iPosShortCut = s.IndexOf('&'); 

            // Did we found an & or is it at the end of the string 
            if (iPosShortCut < 0 || iPosShortCut + 1 >= s.Length)
            {
                return null;
            } 

            // Build the result string 
            return ST.Get(STID.KeyAlt) + "+" + s[iPosShortCut + 1]; 
        }
 
        // Extend an existing RunTimeID by one element
        internal static int[] AppendToRuntimeId(int[] baseID, int id)
        {
            // For the base case, where parent is a hwnd, baseID will be null, 
            // so use AppendRuntimeId instead. UIA will then glue that to the ID
            // of the parent HWND. 
            if(baseID == null) 
                baseID = new int[] { AutomationInteropProvider.AppendRuntimeId };
 
            int len = baseID.Length;
            int[] newID = new int[len + 1];

            baseID.CopyTo(newID, 0); 
            newID[len] = id;
            return newID; 
        } 

        internal static double[] RectArrayToDoubleArray(Rect[] rectArray) 
        {
            if (rectArray == null)
                return null;
            double[] doubles = new double[rectArray.Length * 4]; 
            int scan = 0;
            for (int i = 0; i < rectArray.Length; i++) 
            { 
                doubles[scan++] = rectArray[i].X;
                doubles[scan++] = rectArray[i].Y; 
                doubles[scan++] = rectArray[i].Width;
                doubles[scan++] = rectArray[i].Height;
            }
            return doubles; 
        }
 
        // Ensure a window and all its parents are enabled. 
        // If not, throw ElementNotEnabledException.
        internal static void CheckEnabled(IntPtr hwnd) 
        {
            if (!IsEnabled(hwnd))
            {
                throw new ElementNotEnabledException(); 
            }
        } 
 
        // Checks to see if the process owning the hwnd is currently in menu mode
        // and takes steps to exit menu mode if it is 
        internal static void ClearMenuMode()
        {
            // Check if we're in menu mode with helper method.
            if (InMenuMode()) 
            {
                // If we are, send an alt keypress to escape 
                Input.SendKeyboardInput(Key.LeftAlt, true); 
                Input.SendKeyboardInput(Key.LeftAlt, false);
 
                // Wait for a few milliseconds for this operation to be completed
                long dwTicks = (long)Environment.TickCount;

                // Wait until the action has been completed 
                while (InMenuMode() && ((long)Environment.TickCount - dwTicks) < MenuTimeOut)
                { 
                    // Sleep the shortest amount of time possible while still guaranteeing that some sleep occurs 
                    System.Threading.Thread.Sleep(1);
                } 
            }
        }

        internal static bool CloseHandle(IntPtr processHandle) 
        {
            bool result = UnsafeNativeMethods.CloseHandle(processHandle); 
            int lastWin32Error = Marshal.GetLastWin32Error(); 

            if (!result) 
            {
                ThrowWin32ExceptionsIfError(lastWin32Error);
            }
 
            return result;
        } 
 
        // Compares 2 raw elements and returns true if equal, false otherwise
        internal static bool Compare(ProxySimple el1, ProxySimple el2) 
        {
            int[] a1 = el1.GetRuntimeId();
            int[] a2 = el2.GetRuntimeId();
            int l = a1.Length; 

            if (l != a2.Length) 
                return false; 

            for (int i = 0; i < l; i++) 
            {
                if (a1[i] != a2[i])
                {
                    return false; 
                }
            } 
 
            return true;
        } 

        internal static IntPtr DispatchMessage(ref NativeMethods.MSG msg)
        {
            // From the Windows SDK documentation: 
            // The return value specifies the value returned by the window procedure.
            // Although its meaning depends on the message being dispatched, the return 
            // value generally is ignored. 
#pragma warning suppress 6031, 6523
            return UnsafeNativeMethods.DispatchMessage(ref msg); 
        }


        internal unsafe static bool EnumChildWindows(IntPtr hwnd, NativeMethods.EnumChildrenCallbackVoid lpEnumFunc, void* lParam) 
        {
            bool result = UnsafeNativeMethods.EnumChildWindows(hwnd, lpEnumFunc, lParam); 
            int lastWin32Error = Marshal.GetLastWin32Error(); 

            if (!result) 
            {
                ThrowWin32ExceptionsIfError(lastWin32Error);
            }
 
            return result;
        } 
 
        internal static IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string className, string wndName)
        { 
            // The failure case of this API may also be a valid return.  GetLastError() is need to determine a true failure state.
            // Clear the last error code to make sure we have a good starting condition to determine error state.
            UnsafeNativeMethods.SetLastError(0);
            IntPtr result = UnsafeNativeMethods.FindWindowEx(hwndParent, hwndChildAfter, className, wndName); 
            int lastWin32Error = Marshal.GetLastWin32Error();
 
            if (result == IntPtr.Zero) 
            {
                ThrowWin32ExceptionsIfError(lastWin32Error); 
            }

            return result;
        } 

        internal static string GetClassName(IntPtr hwnd) 
        { 
            StringBuilder sb = new StringBuilder(NativeMethods.MAX_PATH + 1);
 
            int result = UnsafeNativeMethods.GetClassName(hwnd, sb, NativeMethods.MAX_PATH);
            int lastWin32Error = Marshal.GetLastWin32Error();

            if (result == 0) 
            {
                ThrowWin32ExceptionsIfError(lastWin32Error); 
                return ""; 
            }
 
            return sb.ToString();
        }

        // Get the name of a control and conditionally strip mnemonic. 
        // label is the hwnd of the control that is funtioning as the label.  Use GetLabelhwnd to find this.
        // If stripMnemonic is true, amperstrands characters will be stripped out. 
        internal static string GetControlName(IntPtr label, bool stripMnemonic) 
        {
            if (label == IntPtr.Zero) 
            {
                return null;
            }
 
            StringBuilder sb = new StringBuilder(MaxLengthNameProperty);
 
            int result = UnsafeNativeMethods.GetWindowText(label, sb, MaxLengthNameProperty); 
            int lastWin32Error = Marshal.GetLastWin32Error();
 
            if (result == 0)
            {
                ThrowWin32ExceptionsIfError(lastWin32Error);
                return null; 
            }
 
            return stripMnemonic ? StripMnemonic(sb.ToString()) : sb.ToString(); 

        } 

        internal static bool GetClientRectInScreenCoordinates(IntPtr hwnd, ref NativeMethods.Win32Rect rc)
        {
            rc = NativeMethods.Win32Rect.Empty; 

            if (!GetClientRect(hwnd, ref rc)) 
            { 
                return false;
            } 

            NativeMethods.Win32Point leftTop = new NativeMethods.Win32Point(rc.left, rc.top);
            if (!MapWindowPoints(hwnd, IntPtr.Zero, ref leftTop, 1))
            { 
                return false;
            } 
 
            NativeMethods.Win32Point rightBottom = new NativeMethods.Win32Point(rc.right, rc.bottom);
            if (!MapWindowPoints(hwnd, IntPtr.Zero, ref rightBottom, 1)) 
            {
                return false;
            }
 
            rc = new NativeMethods.Win32Rect(leftTop.x, leftTop.y, rightBottom.x, rightBottom.y);
            return true; 
        } 

        internal static bool GetClientRect(IntPtr hwnd, ref NativeMethods.Win32Rect rc) 
        {
            bool result = UnsafeNativeMethods.GetClientRect(hwnd, ref rc);
            int lastWin32Error = Marshal.GetLastWin32Error();
 
            if (!result)
            { 
                ThrowWin32ExceptionsIfError(lastWin32Error); 
            }
 
            // When the control is right to left GetClentRect() will return a rectangle with left > right.
            // Normalize thesee rectangle back to left to right.
            rc.Normalize(IsLayoutRTL(hwnd));
 
            return result;
        } 
 
        internal static bool GetComboBoxInfo(IntPtr hwnd, ref NativeMethods.COMBOBOXINFO cbi)
        { 
            bool result = UnsafeNativeMethods.GetComboBoxInfo(hwnd, ref cbi);
            int lastWin32Error = Marshal.GetLastWin32Error();

            if (!result) 
            {
                ThrowWin32ExceptionsIfError(lastWin32Error); 
            } 

            return result; 
        }

        internal static bool GetCursorPos(ref NativeMethods.Win32Point pt)
        { 
            // Vista and beyond use GetPhysicalCursorPos which handles DPI issues
            bool result = (System.Environment.OSVersion.Version.Major >= 6) ? UnsafeNativeMethods.GetPhysicalCursorPos(ref pt) 
                                                                            : UnsafeNativeMethods.GetCursorPos(ref pt); 
            int lastWin32Error = Marshal.GetLastWin32Error();
 
            if (!result)
            {
                ThrowWin32ExceptionsIfError(lastWin32Error);
            } 

            return result; 
        } 

 
        internal static IntPtr GetDC(IntPtr hwnd)
        {
            IntPtr hdc = UnsafeNativeMethods.GetDC(hwnd);
            int lastWin32Error = Marshal.GetLastWin32Error(); 

            if (hdc == IntPtr.Zero) 
            { 
                ThrowWin32ExceptionsIfError(lastWin32Error);
            } 

            return hdc;
        }
 
        internal static IntPtr GetFocusedWindow()
        { 
            NativeMethods.GUITHREADINFO gui; 

            return ProxyGetGUIThreadInfo(0, out gui) ? gui.hwndFocus : IntPtr.Zero; 
        }

        internal static string GetItemToolTipText(IntPtr hwnd, IntPtr hwndToolTip, int item)
        { 
            if (hwndToolTip != IntPtr.Zero)
            { 
                // We've found the tooltip window, so we won't need to scan for it. 

                // Got a tooltip window - use it. 
                NativeMethods.TOOLINFO tool = new NativeMethods.TOOLINFO();
                tool.Init(Marshal.SizeOf(typeof(NativeMethods.TOOLINFO)));

                tool.hwnd = hwnd; 
                tool.uId = item;
 
                return XSendMessage.GetItemText(hwndToolTip, tool); 
            }
            else 
            {
                // Control doesn't know its tooltip window - instead scan for one...

                // Enum the top-level windows owned by this thread... 
                uint processId;
                uint threadId = GetWindowThreadProcessId(hwnd, out processId); 
 
                UnsafeNativeMethods.ENUMTOOLTIPWINDOWINFO info = new UnsafeNativeMethods.ENUMTOOLTIPWINDOWINFO();
                info.hwnd = hwnd; 
                info.id = item;
                info.name = "";

                UnsafeNativeMethods.EnumThreadWndProc enumToolTipWindows = new UnsafeNativeMethods.EnumThreadWndProc(EnumToolTipWindows); 
                GCHandle gch = GCHandle.Alloc(enumToolTipWindows);
                UnsafeNativeMethods.EnumThreadWindows(threadId, enumToolTipWindows, ref info); 
                gch.Free(); 

                return info.name; 
            }
        }

        // -------------------------------------------------------------------------- 
        //
        //  GetLabelhwnd() 
        // 
        //  This walks backwards among peer windows to find a static field.  It stops
        //  if it gets to the front or hits a group/tabstop, just like the dialog 
        //  manager does.
        //
        // Ported from OleAcc\Client.CPP
        // ------------------------------------------------------------------------- 

        internal static IntPtr GetLabelhwnd(IntPtr hwnd) 
        { 
            // Sanity check
            if (!UnsafeNativeMethods.IsWindow(hwnd)) 
            {
                return IntPtr.Zero;
            }
 
            // Only get labels for child windows - not top-level windows or desktop
            IntPtr hwndParent = Misc.GetParent(hwnd); 
            if (hwndParent == IntPtr.Zero || hwndParent == UnsafeNativeMethods.GetDesktopWindow()) 
            {
                return IntPtr.Zero; 
            }

            IntPtr peer = hwnd;
 
            // If GetWindow fails we're going to exit, no need to call Marshal.GetLastWin32Error
#pragma warning suppress 56523 
            while ((peer = UnsafeNativeMethods.GetWindow(peer, NativeMethods.GW_HWNDPREV)) != IntPtr.Zero) 
            {
                // 
                // Is this a static dude?
                //
                int code = Misc.ProxySendMessageInt(peer, NativeMethods.WM_GETDLGCODE, IntPtr.Zero, IntPtr.Zero);
                if ((code & NativeMethods.DLGC_STATIC) == NativeMethods.DLGC_STATIC) 
                {
                    // 
                    // Great, we've found our label. 
                    //
                    return peer; 
                }

                //
                // Skip invisible controls. 
                // Note that we do this after checking if its a static, so that we give invisible statics a chance.
                // Using invisible statics is an easy workaround to add names to controls without changing the visual UI. 
                // 
                // If GetWindowLong fails we're going to exit, no need to call Marshal.GetLastWin32Error
#pragma warning suppress 56523 
                int style = UnsafeNativeMethods.GetWindowLong(peer, NativeMethods.GWL_STYLE);
                if ((style & NativeMethods.WS_VISIBLE) != 0)
                    continue;
 
                //
                // Is this a tabstop or group?  If so, bail out now. 
                // 
                if ((style & (NativeMethods.WS_GROUP | NativeMethods.WS_TABSTOP)) != 0)
                    break; 
            }

            // Failed to find a suitable peer
            return IntPtr.Zero; 
        }
 
        internal static bool GetMenuBarInfo(IntPtr hwnd, int idObject, uint item, ref NativeMethods.MENUBARINFO mbi) 
        {
            // The failure case of this API may also be a valid return.  GetLastError() is need to determine a true failure state. 
            // Clear the last error code to make sure we have a good starting condition to determine error state.
            UnsafeNativeMethods.SetLastError(0);
            bool result = UnsafeNativeMethods.GetMenuBarInfo(hwnd, idObject, item, ref mbi);
            int lastWin32Error = Marshal.GetLastWin32Error(); 

            if (!result) 
            { 
                ThrowWin32ExceptionsIfError(lastWin32Error);
            } 

            return result;
        }
 
        internal static int GetMenuItemCount(IntPtr hmenu)
        { 
            int count = UnsafeNativeMethods.GetMenuItemCount(hmenu); 
            int lastWin32Error = Marshal.GetLastWin32Error();
 
            if (count == -1)
            {
                ThrowWin32ExceptionsIfError(lastWin32Error);
            } 

            return count; 
        } 

        internal static bool GetMenuItemInfo(IntPtr hmenu, int item, bool byPosition, ref NativeMethods.MENUITEMINFO menuItemInfo) 
        {
            bool result = UnsafeNativeMethods.GetMenuItemInfo(hmenu, item, byPosition, ref menuItemInfo);
            int lastWin32Error = Marshal.GetLastWin32Error();
 
            if (!result)
            { 
                ThrowWin32ExceptionsIfError(lastWin32Error); 
            }
 
            return result;
        }

        internal static bool GetMenuItemRect(IntPtr hwnd, IntPtr hmenu, int item, out NativeMethods.Win32Rect rc) 
        {
            bool result = UnsafeNativeMethods.GetMenuItemRect(hwnd, hmenu, item, out rc); 
            int lastWin32Error = Marshal.GetLastWin32Error(); 

            if (!result) 
            {
                ThrowWin32ExceptionsIfError(lastWin32Error);
            }
 
            return result;
        } 
 
        internal static bool GetMessage(ref NativeMethods.MSG msg, IntPtr hwnd, int msgFilterMin, int msgFilterMax)
        { 
            int result = UnsafeNativeMethods.GetMessage(ref msg, hwnd, msgFilterMin, msgFilterMax);
            int lastWin32Error = Marshal.GetLastWin32Error();

            bool success = (result != 0 && result != -1); 
            if (!success)
            { 
                ThrowWin32ExceptionsIfError(lastWin32Error); 
            }
 
            return success;
        }

        internal static int GetObjectW(IntPtr hObject, int size, ref NativeMethods.LOGFONT lf) 
        {
            int result = UnsafeNativeMethods.GetObjectW(hObject, size, ref lf); 
            int lastWin32Error = Marshal.GetLastWin32Error(); 

            if (result == 0) 
            {
                ThrowWin32ExceptionsIfError(lastWin32Error);
            }
 
            return result;
        } 
 
        internal static IntPtr GetParent(IntPtr hwnd)
        { 
            // The failure case of this API may also be a valid return.  GetLastError() is need to determine a true failure state.
            // Clear the last error code to make sure we have a good starting condition to determine error state.
            UnsafeNativeMethods.SetLastError(0);
            IntPtr hwndParent = UnsafeNativeMethods.GetAncestor(hwnd, NativeMethods.GA_PARENT); 
            int lastWin32Error = Marshal.GetLastWin32Error();
 
            if (hwndParent == IntPtr.Zero) 
            {
                ThrowWin32ExceptionsIfError(lastWin32Error); 
            }

            return hwndParent;
        } 

        internal static bool GetScrollBarInfo(IntPtr hwnd, int fnBar, ref NativeMethods.ScrollBarInfo sbi) 
        { 
            bool result = UnsafeNativeMethods.GetScrollBarInfo(hwnd, fnBar, ref sbi);
            int lastWin32Error = Marshal.GetLastWin32Error(); 

            if (!result)
            {
                ThrowWin32ExceptionsIfError(lastWin32Error); 
            }
 
            return result; 
        }
 
        internal static bool GetScrollInfo(IntPtr hwnd, int fnBar, ref NativeMethods.ScrollInfo si)
        {
            bool result = UnsafeNativeMethods.GetScrollInfo(hwnd, fnBar, ref si);
            int lastWin32Error = Marshal.GetLastWin32Error(); 

            if (!result) 
            { 
                // 1447     ERROR_NO_SCROLLBARS     The window does not have scroll bars.
                // If GetScrollInfo() fails with ERROR_NO_SCROLLBARS then there is no scroll information 
                // to get.  Just return false saying that GetScrollInfo() could not get the information
                if (lastWin32Error == 1447)
                {
                    return false; 
                }
                ThrowWin32ExceptionsIfError(lastWin32Error); 
            } 

            return result; 
        }

        internal static int GetTextExtentPoint32(IntPtr hdc, string text, int length, out NativeMethods.SIZE size)
        { 
            // The failure case of this API may also be a valid return.  GetLastError() is need to determine a true failure state.
            // Clear the last error code to make sure we have a good starting condition to determine error state. 
            UnsafeNativeMethods.SetLastError(0); 
            int result = UnsafeNativeMethods.GetTextExtentPoint32(hdc, text, length, out size);
            int lastWin32Error = Marshal.GetLastWin32Error(); 

            if (result == 0)
            {
                ThrowWin32ExceptionsIfError(lastWin32Error); 
            }
 
            return result; 
        }
 
        // Calls a message that retrieves a string, but doesn't take a length argument, in a relatively safe manner.
        // Attempts to rapidly resize in hopes of crashing UI Automation should just crash whatever is rapidly resizing.
        // Param "hwnd" the Window Handle
        // Param "uMsg" the Windows Message 
        // Param "wParam" the Windows wParam
        // Param "maxLength" the size of the string 
        internal static unsafe string GetUnsafeText(IntPtr hwnd, int uMsg, IntPtr wParam, int maxLength) 
        {
            uint pageSize = GetPageSize(); 
            IntPtr memAddr = IntPtr.Zero;     // Ptr to remote mem
            // calculate the size needed for the string
            uint cbSize = (uint)((maxLength + 1) * sizeof(char));
            // resize it to include enough pages for the string, and an extra guarding page, and one extra page to account for shifts. 
            cbSize = ((cbSize / pageSize) + 3) * pageSize;
 
            try 
            {
                // Allocate the space 
                memAddr = VirtualAlloc(IntPtr.Zero, new UIntPtr(cbSize), UnsafeNativeMethods.MEM_COMMIT, UnsafeNativeMethods.PAGE_READWRITE);

                // Allocate the Final page as No Access, so any attempt to write to it will GPF
                VirtualAlloc(new IntPtr((byte *)memAddr.ToPointer() + cbSize - pageSize), new UIntPtr(pageSize), UnsafeNativeMethods.MEM_COMMIT, UnsafeNativeMethods.PAGE_NOACCESS); 

                // Send the message... 
                if (ProxySendMessage(hwnd, uMsg, wParam, memAddr) == IntPtr.Zero) 
                {
                    return ""; 
                }

                String str = new string((char*)memAddr.ToPointer(), 0, maxLength);
                // Note: lots of "old world" strings are null terminated 
                // Leaving the null termination in the System.String may lead
                // to some issues when used with the StringBuilder 
                int nullTermination = str.IndexOf('\0'); 

                if (-1 != nullTermination) 
                {
                    // We need to strip null terminated char and everything behind it from the str
                    str = str.Remove(nullTermination, maxLength - nullTermination);
                } 
                return str;
            } 
            finally 
            {
                // Free the memory 
                if (memAddr != IntPtr.Zero)
                {
                    VirtualFree(memAddr, UIntPtr.Zero, UnsafeNativeMethods.MEM_RELEASE);
                } 
            }
        } 
 
        internal static IntPtr GetWindow(IntPtr hwnd, int cmd)
        { 
            // The failure case of this API may also be a valid return.  GetLastError() is need to determine a true failure state.
            // Clear the last error code to make sure we have a good starting condition to determine error state.
            UnsafeNativeMethods.SetLastError(0);
            IntPtr resultHwnd = UnsafeNativeMethods.GetWindow(hwnd, cmd); 
            int lastWin32Error = Marshal.GetLastWin32Error();
 
            if (resultHwnd == IntPtr.Zero) 
            {
                ThrowWin32ExceptionsIfError(lastWin32Error); 
            }

            return resultHwnd;
        } 

        // Gets the extended style of the window 
        internal static int GetWindowExStyle(IntPtr hwnd) 
        {
            // The failure case of this API may also be a valid return.  GetLastError() is need to determine a true failure state. 
            // Clear the last error code to make sure we have a good starting condition to determine error state.
            UnsafeNativeMethods.SetLastError(0);
            int exstyle = UnsafeNativeMethods.GetWindowLong(hwnd, NativeMethods.GWL_EXSTYLE);
            int lastWin32Error = Marshal.GetLastWin32Error(); 

            if (exstyle == 0) 
            { 
                ThrowWin32ExceptionsIfError(lastWin32Error);
            } 

            return exstyle;
        }
 
        // Gets the id of the window
        internal static int GetWindowId(IntPtr hwnd) 
        { 
            // The failure case of this API may also be a valid return.  GetLastError() is need to determine a true failure state.
            // Clear the last error code to make sure we have a good starting condition to determine error state. 
            UnsafeNativeMethods.SetLastError(0);
            int id = UnsafeNativeMethods.GetWindowLong(hwnd, NativeMethods.GWL_ID);
            int lastWin32Error = Marshal.GetLastWin32Error();
 
            if (id == 0)
            { 
                ThrowWin32ExceptionsIfError(lastWin32Error); 
            }
 
            return id;
        }

        // Gets the parent of the window 
        internal static IntPtr GetWindowParent(IntPtr hwnd)
        { 
            // NOTE: This may have issues in 64-bit. 

            // The failure case of this API may also be a valid return.  GetLastError() is need to determine a true failure state. 
            // Clear the last error code to make sure we have a good starting condition to determine error state.
            UnsafeNativeMethods.SetLastError(0);
            int result = UnsafeNativeMethods.GetWindowLong(hwnd, NativeMethods.GWL_HWNDPARENT);
            int lastWin32Error = Marshal.GetLastWin32Error(); 

            if (result == 0) 
            { 
                ThrowWin32ExceptionsIfError(lastWin32Error);
            } 

            return (IntPtr)result;
        }
 
        internal static bool GetWindowRect(IntPtr hwnd, ref NativeMethods.Win32Rect rc)
        { 
            bool result = UnsafeNativeMethods.GetWindowRect(hwnd, ref rc); 
            int lastWin32Error = Marshal.GetLastWin32Error();
 
            if (!result)
            {
                ThrowWin32ExceptionsIfError(lastWin32Error);
            } 
            return result;
        } 
 
        // Gets the style of the window
        internal static int GetWindowStyle(IntPtr hwnd) 
        {
            // The failure case of this API may also be a valid return.  GetLastError() is need to determine a true failure state.
            // Clear the last error code to make sure we have a good starting condition to determine error state.
            UnsafeNativeMethods.SetLastError(0); 
            int style = UnsafeNativeMethods.GetWindowLong(hwnd, NativeMethods.GWL_STYLE);
            int lastWin32Error = Marshal.GetLastWin32Error(); 
 
            if (style == 0)
            { 
                ThrowWin32ExceptionsIfError(lastWin32Error);
            }

            return style; 
        }
 
        internal static uint GetWindowThreadProcessId(IntPtr hwnd, out uint processId) 
        {
            // GetWindowThreadProcessId does use SetLastError().  So a call to GetLastError() would be meanless. 
            // Disabling the PreSharp warning.
#pragma warning suppress 6523
            uint threadId = UnsafeNativeMethods.GetWindowThreadProcessId(hwnd, out processId);
 
            if (threadId == 0)
            { 
                throw new ElementNotAvailableException(); 
            }
 
            return threadId;
        }

        internal static short GlobalAddAtom(string atomName) 
        {
            short atom = UnsafeNativeMethods.GlobalAddAtom(atomName); 
            int lastWin32Error = Marshal.GetLastWin32Error(); 
            if (atom == 0)
            { 
                ThrowWin32ExceptionsIfError(lastWin32Error);
            }
            return atom;
        } 

        internal static short GlobalDeleteAtom(short atom) 
        { 
            // This API does not have an error condition.  GetLastError is used to determine if an error occured.
            // So, clear the last error code to make sure we have a good starting condition to determine error state. 
            UnsafeNativeMethods.SetLastError(0);
            short result = UnsafeNativeMethods.GlobalDeleteAtom(atom);
            ThrowWin32ExceptionsIfError(Marshal.GetLastWin32Error());
            return result; 
        }
 
        // detect if we're in the menu mode 
        internal static bool InMenuMode()
        { 
            NativeMethods.GUITHREADINFO gui;
            return (ProxyGetGUIThreadInfo(0, out gui) && (IsBitSet(gui.dwFlags, NativeMethods.GUI_INMENUMODE)));
        }
 
        internal static bool IsBitSet(int flags, int bit)
        { 
            return (flags & bit) == bit; 
        }
 
        // Check if window is really enabled, taking parent state into account.
        internal static bool IsEnabled(IntPtr hwnd)
        {
 
            // Navigate up parent chain. If any ancestor window is
            // not enabled, then that has the effect of disabling this window. 
            // All ancestor windows must be enabled for this window to be enabled. 
            for (; ; )
            { 
                if (!SafeNativeMethods.IsWindowEnabled(hwnd))
                {
                    return false;
                } 

                hwnd = UnsafeNativeMethods.GetAncestor(hwnd, NativeMethods.GA_PARENT); 
                if (hwnd == IntPtr.Zero) 
                {
                    return true; 
                }
            }
        }
 
        internal static bool IsControlRTL(IntPtr hwnd)
        { 
            int exStyle = GetWindowExStyle(hwnd); 
            return IsBitSet(exStyle, NativeMethods.WS_EX_LAYOUTRTL) || IsBitSet(exStyle, NativeMethods.WS_EX_RTLREADING);
        } 

        internal static bool IsLayoutRTL(IntPtr hwnd)
        {
            return IsBitSet(GetWindowExStyle(hwnd), NativeMethods.WS_EX_LAYOUTRTL); 
        }
 
        internal static bool IsReadingRTL(IntPtr hwnd) 
        {
            return IsBitSet(GetWindowExStyle(hwnd), NativeMethods.WS_EX_RTLREADING); 
        }

        internal static bool IntersectRect(ref NativeMethods.Win32Rect rcDest, ref NativeMethods.Win32Rect rc1, ref NativeMethods.Win32Rect rc2)
        { 
            bool result = SafeNativeMethods.IntersectRect(ref rcDest, ref rc1, ref rc2);
            int lastWin32Error = Marshal.GetLastWin32Error(); 
 
            if (!result)
            { 
                ThrowWin32ExceptionsIfError(lastWin32Error);
            }

            return result; 
        }
 
        // Call IsCriticalException w/in a catch-all-exception handler to allow critical exceptions 
        // to be thrown (this is copied from exception handling code in WinForms but feel free to
        // add new critical exceptions).  Usage: 
        //      try
        //      {
        //          Somecode();
        //      } 
        //      catch (Exception e)
        //      { 
        //          if (Misc.IsCriticalException(e)) 
        //              throw;
        //          // ignore non-critical errors from external code 
        //      }
        internal static bool IsCriticalException(Exception e)
        {
            return e is NullReferenceException || e is StackOverflowException || e is OutOfMemoryException || e is System.Threading.ThreadAbortException; 
        }
 
        // this is to determine is an item is visible.  The assumption is that the items here are not hwnds 
        // and that they are clipped by there parent.  For example this is called by the WindowsListBox.
        // In that case the hwnd is the list box and the itemRect would be a list item this code checks to see 
        // if the item is scrolled out of view.
        static internal bool IsItemVisible(IntPtr hwnd, ref NativeMethods.Win32Rect itemRect)
        {
            NativeMethods.Win32Rect clientRect = new NativeMethods.Win32Rect(0, 0, 0, 0); 
            if (!GetClientRectInScreenCoordinates(hwnd, ref clientRect))
                return false; 
 
            NativeMethods.Win32Rect intersection = new NativeMethods.Win32Rect(0, 0, 0, 0);
 
            // Returns true if the passed in itemRect overlaps with the client area of the hwnd this API
            // does not modify clientRect or itemRect
            return IntersectRect(ref intersection, ref clientRect, ref itemRect);
        } 

        static internal bool IsItemVisible(ref NativeMethods.Win32Rect parentRect, ref NativeMethods.Win32Rect itemRect) 
        { 
            NativeMethods.Win32Rect intersection = new NativeMethods.Win32Rect(0, 0, 0, 0);
 
            // Returns true if the passed in itemRect overlaps with the client area of the hwnd this API
            // does not modify clientRect or itemRect
            return IntersectRect(ref intersection, ref parentRect, ref itemRect);
        } 

        static internal bool IsItemVisible(ref NativeMethods.Win32Rect parentRect, ref Rect itemRect) 
        { 
            NativeMethods.Win32Rect itemRc = new NativeMethods.Win32Rect(itemRect);
            NativeMethods.Win32Rect intersection = new NativeMethods.Win32Rect(0, 0, 0, 0); 

            // Returns true if the passed in itemRect overlaps with the client area of the hwnd this API
            // does not modify clientRect or itemRect
            return IntersectRect(ref intersection, ref parentRect, ref itemRc); 
        }
 
        static internal bool IsItemVisible(ref Rect parentRect, ref NativeMethods.Win32Rect itemRect) 
        {
            NativeMethods.Win32Rect parentRc = new NativeMethods.Win32Rect(parentRect); 
            NativeMethods.Win32Rect intersection = new NativeMethods.Win32Rect(0, 0, 0, 0);

            // Returns true if the passed in itemRect overlaps with the client area of the hwnd this API
            // does not modify clientRect or itemRect 
            return IntersectRect(ref intersection, ref parentRc, ref itemRect);
        } 
 
        static internal bool IsItemVisible(ref Rect parentRect, ref Rect itemRect)
        { 
            NativeMethods.Win32Rect itemRc = new NativeMethods.Win32Rect(itemRect);
            NativeMethods.Win32Rect parentRc = new NativeMethods.Win32Rect(parentRect);
            NativeMethods.Win32Rect intersection = new NativeMethods.Win32Rect(0, 0, 0, 0);
 
            // Returns true if the passed in itemRect overlaps with the client area of the hwnd this API
            // does not modify clientRect or itemRect 
            return IntersectRect(ref intersection, ref parentRc, ref itemRc); 
        }
 
        internal static bool IsProgmanWindow(IntPtr hwnd)
        {
            while (hwnd != IntPtr.Zero)
            { 
                if (GetClassName(hwnd).CompareTo("Progman") == 0)
                { 
                    return true; 
                }
                hwnd = UnsafeNativeMethods.GetAncestor(hwnd, NativeMethods.GA_PARENT); 
            }
            return false;
        }
 
        internal static bool IsWow64Process(MS.Internal.AutomationProxies.SafeProcessHandle hProcess, out bool Wow64Process)
        { 
            bool result = UnsafeNativeMethods.IsWow64Process(hProcess, out Wow64Process); 
            int lastWin32Error = Marshal.GetLastWin32Error();
 
            if (!result)
            {
                ThrowWin32ExceptionsIfError(lastWin32Error);
            } 

            return result; 
        } 

        // wrapper for MapWindowPoints 
        internal static bool MapWindowPoints(IntPtr hWndFrom, IntPtr hWndTo, ref NativeMethods.Win32Rect rect, int cPoints)
        {
            // The failure case of this API may also be a valid return.  GetLastError() is need to determine a true failure state.
            // Clear the last error code to make sure we have a good starting condition to determine error state. 
            UnsafeNativeMethods.SetLastError(0);
            int mappingOffset = UnsafeNativeMethods.MapWindowPoints(hWndFrom, hWndTo, ref rect, cPoints); 
            int lastWin32Error = Marshal.GetLastWin32Error(); 
            if (mappingOffset == 0)
            { 
                // When mapping points to/from Progman and its children MapWindowPoints may fail with error code 1400
                // Invalid Window Handle.  Since Progman is the desktop no mapping is need.
                if ((IsProgmanWindow(hWndFrom) && hWndTo == IntPtr.Zero) ||
                    (hWndFrom == IntPtr.Zero && IsProgmanWindow(hWndTo))) 
                {
                    lastWin32Error = 0; 
                } 

                ThrowWin32ExceptionsIfError(lastWin32Error); 

                // If the coordinates is at the origin a zero return is valid.
                // Use GetLastError() to check that. Error code 0 is "Operation completed successfull".
                return lastWin32Error == 0; 
            }
 
            return true; 
        }
 
        // wrapper for MapWindowPoints
        internal static bool MapWindowPoints(IntPtr hWndFrom, IntPtr hWndTo, ref NativeMethods.Win32Point pt, int cPoints)
        {
            // The failure case of this API may also be a valid return.  GetLastError() is need to determine a true failure state. 
            // Clear the last error code to make sure we have a good starting condition to determine error state.
            UnsafeNativeMethods.SetLastError(0); 
            int mappingOffset = UnsafeNativeMethods.MapWindowPoints(hWndFrom, hWndTo, ref pt, cPoints); 
            int lastWin32Error = Marshal.GetLastWin32Error();
            if (mappingOffset == 0) 
            {
                // When mapping points to/from Progman and its children MapWindowPoints may fail with error code 1400
                // Invalid Window Handle.  Since Progman is the desktop no mapping is need.
                if ((IsProgmanWindow(hWndFrom) && hWndTo == IntPtr.Zero) || 
                    (hWndFrom == IntPtr.Zero && IsProgmanWindow(hWndTo)))
                { 
                    lastWin32Error = 0; 
                }
 
                ThrowWin32ExceptionsIfError(lastWin32Error);

                // If the coordinates is at the origin a zero return is valid.
                // Use GetLastError() to check that. Error code 0 is "Operation completed successfull". 
                return lastWin32Error == 0;
            } 
 
            return true;
        } 

        // Move the mouse to the x, y location and perfoms a mouse clik
        // The mouse is then brough back to the original location.
        internal static void MouseClick(int x, int y) 
        {
            MouseClick(x, y, false); 
        } 

        // Move the mouse to the x, y location and perfoms either 
        // a single of double clik depending on the fDoubleClick parameter
        // The mouse is then brough back to the original location.
        internal static void MouseClick(int x, int y, bool fDoubleClick)
        { 
            NativeMethods.Win32Point ptPrevious = new NativeMethods.Win32Point();
            bool fSetOldCursorPos = GetCursorPos(ref ptPrevious); 
            bool mouseSwapped = UnsafeNativeMethods.GetSystemMetrics(NativeMethods.SM_SWAPBUTTON) != 0; 

            Input.SendMouseInput(x, y, 0, SendMouseInputFlags.Move | SendMouseInputFlags.Absolute); 

            Input.SendMouseInput(0, 0, 0, mouseSwapped ? SendMouseInputFlags.RightDown : SendMouseInputFlags.LeftDown);
            Input.SendMouseInput(0, 0, 0, mouseSwapped ? SendMouseInputFlags.RightUp : SendMouseInputFlags.LeftUp);
 
            if (fDoubleClick)
            { 
                Input.SendMouseInput(0, 0, 0, mouseSwapped ? SendMouseInputFlags.RightDown : SendMouseInputFlags.LeftDown); 
                Input.SendMouseInput(0, 0, 0, mouseSwapped ? SendMouseInputFlags.RightUp : SendMouseInputFlags.LeftUp);
            } 

            // toolbar items don't have time to proccess the mouse click if we move it back too soon
            // so wait a small amount of time to give them a chance.  A value of 10 made this work
            // on a 2gig dual proc machine so 50 should cover a slower machine. 
            System.Threading.Thread.Sleep(50);
 
            // Set back the mouse position where it was 
            if (fSetOldCursorPos)
            { 
                Input.SendMouseInput(ptPrevious.x, ptPrevious.y, 0, SendMouseInputFlags.Move | SendMouseInputFlags.Absolute);
            }
        }
 
        [SecurityPermission(SecurityAction.Demand, UnmanagedCode = true)]
        internal static int MsgWaitForMultipleObjects(SafeWaitHandle handle, bool waitAll, int milliseconds, int wakeMask) 
        { 
            int terminationEvent, lastWin32Error;
            if (handle == null) 
            {
                terminationEvent = UnsafeNativeMethods.MsgWaitForMultipleObjects(0, null, waitAll, milliseconds, wakeMask);
                lastWin32Error = Marshal.GetLastWin32Error();
            } 
            else
            { 
                RuntimeHelpers.PrepareConstrainedRegions(); 
                bool fRelease = false;
                try 
                {
                    handle.DangerousAddRef(ref fRelease);
                    IntPtr[] handles = { handle.DangerousGetHandle() };
                    terminationEvent = UnsafeNativeMethods.MsgWaitForMultipleObjects(1, handles, waitAll, milliseconds, wakeMask); 
                    lastWin32Error = Marshal.GetLastWin32Error();
                } 
                finally 
                {
                    if (fRelease) 
                    {
                        handle.DangerousRelease();
                    }
                } 
            }
            if (terminationEvent == NativeMethods.WAIT_FAILED) 
            { 
                ThrowWin32ExceptionsIfError(lastWin32Error);
            } 
            return terminationEvent;
        }

        internal static IntPtr OpenProcess(int flags, bool inherit, uint processId, IntPtr hwnd) 
        {
            IntPtr processHandle = UnsafeNativeMethods.OpenProcess(flags, inherit, processId); 
            int lastWin32Error = Marshal.GetLastWin32Error(); 

            // If we fail due to permission issues, if we're on vista, try the hooking technique 
            // to access the process instead.
            if (processHandle == IntPtr.Zero
             && lastWin32Error == 5/*ERROR_ACCESS_DENIED*/
             && System.Environment.OSVersion.Version.Major >= 6) 
            {
                try 
                { 
                    processHandle = UnsafeNativeMethods.GetProcessHandleFromHwnd(hwnd);
                    lastWin32Error = Marshal.GetLastWin32Error(); 
                }
                catch(EntryPointNotFoundException)
                {
                    // Ignore; until OLEACC propogates into Vista builds, the entry point may not be present. 
                }
 
            } 

            if (processHandle == IntPtr.Zero) 
            {
                ThrowWin32ExceptionsIfError(lastWin32Error);
            }
 
            return processHandle;
        } 
 
        // wrapper for PostMessage
        internal static void PostMessage(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam) 
        {
            bool result = UnsafeNativeMethods.PostMessage(hwnd, msg, wParam, lParam);
            int lastWin32Error = Marshal.GetLastWin32Error();
            if (!result) 
            {
                ThrowWin32ExceptionsIfError(lastWin32Error); 
            } 
        }
 
        // Returns the Win32 Class Name for an hwnd
        internal static string ProxyGetClassName(IntPtr hwnd)
        {
            const int OBJID_QUERYCLASSNAMEIDX = unchecked(unchecked((int)0xFFFFFFF4)); 
            const int QUERYCLASSNAME_BASE = 65536;
 
            // Call ProxySendMessage ignoring the timeout 
            //
            int index = ProxySendMessageInt(hwnd, NativeMethods.WM_GETOBJECT, IntPtr.Zero, (IntPtr)OBJID_QUERYCLASSNAMEIDX, true); 

            if (index >= QUERYCLASSNAME_BASE && index - QUERYCLASSNAME_BASE < _asClassNames.Length)
            {
                return _asClassNames[index - QUERYCLASSNAME_BASE]; 
            }
            else 
            { 
                return  RealGetWindowClass(hwnd);
            } 
        }

        // wrapper for GetGuiThreadInfo
        internal static bool ProxyGetGUIThreadInfo(uint idThread, out NativeMethods.GUITHREADINFO gui) 
        {
            gui = new NativeMethods.GUITHREADINFO(); 
            gui.cbSize = Marshal.SizeOf(gui.GetType()); 

            bool result = UnsafeNativeMethods.GetGUIThreadInfo(idThread, ref gui); 
            int lastWin32Error = Marshal.GetLastWin32Error();

            if (!result)
            { 
                // If the focused thread is on another [secure] desktop, GetGUIThreadInfo
                // will fail with ERROR_ACCESS_DENIED - don't throw an exception for that case, 
                // instead treat as a failure. Callers will treat this as though no window has 
                // focus.
                if (lastWin32Error == 5 /*ERROR_ACCESS_DENIED*/) 
                    return false;

                ThrowWin32ExceptionsIfError(lastWin32Error);
            } 

#if _NEED_DEBUG_OUTPUT 
            bool fCaretBlink = (gui.dwFlags & NativeMethods.GUI_CARETBLINKING) != 0; 
            bool fMoveSize = (gui.dwFlags & NativeMethods.GUI_INMOVESIZE) != 0;
            bool fMenuMode = (gui.dwFlags & NativeMethods.GUI_INMENUMODE) != 0; 
            bool fSystemMenuMode = (gui.dwFlags & NativeMethods.GUI_SYSTEMMENUMODE) != 0;
            bool fPopupMenuMode = (gui.dwFlags & NativeMethods.GUI_POPUPMENUMODE) != 0;

            StringBuilder sbFlag = new StringBuilder(NativeMethods.MAX_PATH); 
            if (fCaretBlink)
            { 
                sbFlag.Append("GUI_CARETBLINKING"); 
            }
            if (fMoveSize) 
            {
                sbFlag.Append(sbFlag.Length > 0 ? " | GUI_INMOVESIZE" : "GUI_INMOVESIZE");
            }
            if (fMenuMode) 
            {
                sbFlag.Append(sbFlag.Length > 0 ? " | GUI_INMENUMODE" : "GUI_INMENUMODE"); 
            } 
            if (fSystemMenuMode)
            { 
                sbFlag.Append(sbFlag.Length > 0 ? " | GUI_SYSTEMMENUMODE" : "GUI_SYSTEMMENUMODE");
            }
            if (fPopupMenuMode)
            { 
                sbFlag.Append(sbFlag.Length > 0 ? " | GUI_POPUPMENUMODE" : "GUI_POPUPMENUMODE");
            } 
 
            StringBuilder sb = new StringBuilder(NativeMethods.MAX_PATH);
            sb.Append("GUITHREADINFO \n\r{"); 
            sb.AppendFormat("\n\r\tcbSize = {0}", gui.cbSize);
            sb.AppendFormat("\n\r\tdwFlags = {0}", gui.dwFlags);
            if (sbFlag.Length > 0)
            { 
                sb.Append(" (");
                sb.Append(sbFlag); 
                sb.Append(")"); 
            }
            sb.AppendFormat("\n\r\thwndActive = 0x{0:x8}", gui.hwndActive.ToInt32()); 
            sb.AppendFormat("\n\r\thwndFocus = 0x{0:x8}", gui.hwndFocus.ToInt32());
            sb.AppendFormat("\n\r\thwndCapture = 0x{0:x8}", gui.hwndCapture.ToInt32());
            sb.AppendFormat("\n\r\thwndMenuOwner = 0x{0:x8}", gui.hwndMenuOwner.ToInt32());
            sb.AppendFormat("\n\r\thwndMoveSize = 0x{0:x8}", gui.hwndMoveSize.ToInt32()); 
            sb.AppendFormat("\n\r\thwndCaret = 0x{0:x8}", gui.hwndCaret.ToInt32());
            sb.AppendFormat("\n\r\trc = ({0}, {1}, {2}, {3})", gui.rc.left, gui.rc.top, gui.rc.right, gui.rc.bottom); 
            sb.Append("\n\r}"); 

            System.Diagnostics.Debug.WriteLine(sb.ToString()); 
#endif

            return result;
        } 

        // The name text based on the WM_GETTEXT message. The text is truncated to a predefined character 
        // length. 
        internal static string ProxyGetText(IntPtr hwnd)
        { 
            return ProxyGetText(hwnd, MaxLengthNameProperty);
        }

        internal static string ProxyGetText(IntPtr hwnd, int length) 
        {
            // if the length is zero don't bother asking for the text. 
            if (length == 0) 
            {
                return ""; 
            }

            // Length passes to SendMessage includes terminating NUL
            StringBuilder str = new StringBuilder(length + 1); 

            // Send the message... 
            ProxySendMessage(hwnd, NativeMethods.WM_GETTEXT, (IntPtr)str.Capacity, str); 

            // We don't try to decifer between a zero length string and an error 
            return str.ToString();
        }

        // wrapper for GetTitleBarInfo 
        internal static bool ProxyGetTitleBarInfo(IntPtr hwnd, out UnsafeNativeMethods.TITLEBARINFO ti)
        { 
            ti = new UnsafeNativeMethods.TITLEBARINFO(); 
            ti.cbSize = Marshal.SizeOf(ti.GetType());
 
            bool result = UnsafeNativeMethods.GetTitleBarInfo(hwnd, ref ti);
            int lastWin32Error = Marshal.GetLastWin32Error();

            if (!result) 
            {
                ThrowWin32ExceptionsIfError(lastWin32Error); 
                return false; 
            }
            return true; 
        }

        internal static bool ProxyGetTitleBarInfoEx(IntPtr hwnd, out UnsafeNativeMethods.TITLEBARINFOEX ti)
        { 
            ti = new UnsafeNativeMethods.TITLEBARINFOEX();
            ti.cbSize = Marshal.SizeOf(ti.GetType()); 
            IntPtr result; 
            IntPtr resultSendMessage = UnsafeNativeMethods.SendMessageTimeout(hwnd, NativeMethods.WM_GETTITLEBARINFOEX, IntPtr.Zero, ref ti, _sendMessageFlags, _sendMessageTimeoutValue, out result);
            int lastWin32Error = Marshal.GetLastWin32Error(); 
            if (resultSendMessage == IntPtr.Zero)
            {
                //Window owner failed to process the message WM_GETTITLEBARINFOEX
                EvaluateSendMessageTimeoutError(lastWin32Error); 
            }
            return true; 
        } 

        // Return the bounding rects for titlebar items or null if they are invisible or offscreen 
        internal static Rect [] GetTitlebarRects(IntPtr hwnd)
        {
            // Vista and beyond
            if (System.Environment.OSVersion.Version.Major >= 6) 
            {
                return GetTitlebarRectsEx(hwnd); 
            } 

            // Up through XP 
            return GetTitlebarRectsXP(hwnd);
        }

        internal static Rect GetTitleBarRect(IntPtr hwnd) 
        {
            UnsafeNativeMethods.TITLEBARINFO ti; 
            if (!Misc.ProxyGetTitleBarInfo(hwnd, out ti) || ti.rcTitleBar.IsEmpty) 
            {
                return Rect.Empty; 
            }

            NativeMethods.MENUBARINFO mbi;
            bool retValue = WindowsMenu.GetMenuBarInfo(hwnd, NativeMethods.OBJID_SYSMENU, 0, out mbi); 

            // Possible that there is no menu 
            int left = (!retValue || mbi.rcBar.IsEmpty) ? ti.rcTitleBar.left : mbi.rcBar.left; 
            return new Rect(left, ti.rcTitleBar.top, ti.rcTitleBar.right - left, ti.rcTitleBar.bottom - ti.rcTitleBar.top);
        } 

        internal static IntPtr ProxySendMessage(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam)
        {
            IntPtr result; 

            IntPtr resultSendMessage = UnsafeNativeMethods.SendMessageTimeout(hwnd, msg, wParam, lParam, _sendMessageFlags, _sendMessageTimeoutValue, out result); 
            int lastWin32Error = Marshal.GetLastWin32Error(); 

            if (resultSendMessage == IntPtr.Zero) 
            {
                EvaluateSendMessageTimeoutError(lastWin32Error);
            }
 
            return result;
        } 
 
        // On a 64-bit platform, the value of the IntPtr is too large to represent as a 32-bit signed integer.
        // An int is a System.Int32.  When an explicit cast of IntPtr to int is done on a 64-bit platform an 
        // OverflowException will occur when the IntPtr value exceeds the range of int. In cases where using
        // SendMessage to get back int (e.g. an item index or an enum value), this version safely truncates
        // from IntPtr to int.
        internal static int ProxySendMessageInt(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam) 
        {
            IntPtr result = ProxySendMessage(hwnd, msg, wParam, lParam); 
            return unchecked((int)(long)result); 
        }
 
        // Same as above but does not throw on timeout
        // @
        internal static IntPtr ProxySendMessage(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, bool ignoreTimeout)
        { 
            IntPtr result;
 
            IntPtr resultSendMessage = UnsafeNativeMethods.SendMessageTimeout(hwnd, msg, wParam, lParam, _sendMessageFlags, _sendMessageTimeoutValue, out result); 
            int lastWin32Error = Marshal.GetLastWin32Error();
 
            if (resultSendMessage == IntPtr.Zero)
            {
                EvaluateSendMessageTimeoutError(lastWin32Error, ignoreTimeout);
            } 

            return result; 
        } 

        // On a 64-bit platform, the value of the IntPtr is too large to represent as a 32-bit signed integer. 
        // An int is a System.Int32.  When an explicit cast of IntPtr to int is done on a 64-bit platform an
        // OverflowException will occur when the IntPtr value exceeds the range of int. In cases where using
        // SendMessage to get back int (e.g. an item index or an enum value), this version safely truncates
        // from IntPtr to int. 
        internal static int ProxySendMessageInt(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, bool ignoreTimeout)
        { 
            IntPtr result = ProxySendMessage(hwnd, msg, wParam, lParam, ignoreTimeout); 
            return unchecked((int)(long)result);
        } 

        internal static IntPtr ProxySendMessage(IntPtr hwnd, int msg, IntPtr wParam, StringBuilder sb)
        {
            IntPtr result; 

            IntPtr resultSendMessage = UnsafeNativeMethods.SendMessageTimeout(hwnd, msg, wParam, sb, _sendMessageFlags, _sendMessageTimeoutValue, out result); 
            int lastWin32Error = Marshal.GetLastWin32Error(); 

            if (resultSendMessage == IntPtr.Zero) 
            {
                EvaluateSendMessageTimeoutError(lastWin32Error);
            }
 
            return result;
        } 
 
        // On a 64-bit platform, the value of the IntPtr is too large to represent as a 32-bit signed integer.
        // An int is a System.Int32.  When an explicit cast of IntPtr to int is done on a 64-bit platform an 
        // OverflowException will occur when the IntPtr value exceeds the range of int. In cases where using
        // SendMessage to get back int (e.g. an item index or an enum value), this version safely truncates
        // from IntPtr to int.
        internal static int ProxySendMessageInt(IntPtr hwnd, int msg, IntPtr wParam, StringBuilder sb) 
        {
            IntPtr result = ProxySendMessage(hwnd, msg, wParam, sb); 
            return unchecked((int)(long)result); 
        }
 
        internal static IntPtr ProxySendMessage(IntPtr hwnd, int msg, IntPtr wParam, ref NativeMethods.Win32Rect lParam)
        {
            IntPtr result;
 
            IntPtr resultSendMessage = UnsafeNativeMethods.SendMessageTimeout(hwnd, msg, wParam, ref lParam, _sendMessageFlags, _sendMessageTimeoutValue, out result);
            int lastWin32Error = Marshal.GetLastWin32Error(); 
 
            if (resultSendMessage == IntPtr.Zero)
            { 
                EvaluateSendMessageTimeoutError(lastWin32Error);
            }

            return result; 
        }
 
        internal static IntPtr ProxySendMessage(IntPtr hwnd, int msg, out int wParam, out int lParam) 
        {
            IntPtr result; 

            IntPtr resultSendMessage = UnsafeNativeMethods.SendMessageTimeout(hwnd, msg, out wParam, out lParam, _sendMessageFlags, _sendMessageTimeoutValue, out result);
            int lastWin32Error = Marshal.GetLastWin32Error();
 
            if (resultSendMessage == IntPtr.Zero)
            { 
                EvaluateSendMessageTimeoutError(lastWin32Error); 
            }
 
            return result;
        }

        // Check if a point is within the bounding Rect of a window 
        internal static bool PtInRect(ref NativeMethods.Win32Rect rc, int x, int y)
        { 
            return x >= rc.left && x < rc.right && y >= rc.top && y < rc.bottom; 
        }
 
        internal static bool PtInRect(ref Rect rc, int x, int y)
        {
            return x >= rc.Left && x < rc.Right && y >= rc.Top && y < rc.Bottom;
        } 

        // Check if a point is within the client Rect of a window 
        internal static bool PtInWindowRect(IntPtr hwnd, int x, int y) 
        {
            NativeMethods.Win32Rect rc = new NativeMethods.Win32Rect(); 

            if (!GetWindowRect(hwnd, ref rc))
            {
                return false; 
            }
            return x >= rc.left && x < rc.right && y >= rc.top && y < rc.bottom; 
        } 

        internal static bool ReadProcessMemory(MS.Internal.AutomationProxies.SafeProcessHandle hProcess, IntPtr source, IntPtr dest, IntPtr size, out int bytesRead) 
        {
            bool result = UnsafeNativeMethods.ReadProcessMemory(hProcess, source, dest, size, out bytesRead);
            int lastWin32Error = Marshal.GetLastWin32Error();
 
            if (!result)
            { 
                ThrowWin32ExceptionsIfError(lastWin32Error); 
            }
 
            return result;
        }

        internal static bool ReadProcessMemory(MS.Internal.AutomationProxies.SafeProcessHandle hProcess, IntPtr source, MS.Internal.AutomationProxies.SafeCoTaskMem destAddress, IntPtr size, out int bytesRead) 
        {
            bool result = UnsafeNativeMethods.ReadProcessMemory(hProcess, source, destAddress, size, out bytesRead); 
            int lastWin32Error = Marshal.GetLastWin32Error(); 

            if (!result) 
            {
                ThrowWin32ExceptionsIfError(lastWin32Error);
            }
 
            return result;
        } 
 
        // Get the class name
        internal static string RealGetWindowClass(IntPtr hwnd) 
        {
            System.Text.StringBuilder className = new System.Text.StringBuilder(NativeMethods.MAX_PATH + 1);

            uint result = UnsafeNativeMethods.RealGetWindowClass(hwnd, className, NativeMethods.MAX_PATH); 
            int lastWin32Error = Marshal.GetLastWin32Error();
 
            if (result == 0) 
            {
                ThrowWin32ExceptionsIfError(lastWin32Error); 
                return "";
            }

            return className.ToString(); 
        }
 
        internal static bool RegisterHotKey(IntPtr hwnd, short atom, int modifiers, int vk) 
        {
            bool result = UnsafeNativeMethods.RegisterHotKey(hwnd, atom, modifiers, vk); 
            int lastWin32Error = Marshal.GetLastWin32Error();

            if (!result)
            { 
                ThrowWin32ExceptionsIfError(lastWin32Error);
            } 
 
            return result;
        } 

        internal static int ReleaseDC(IntPtr hwnd, IntPtr hdc)
        {
            // If ReleaseDC fails we will not do anything with that information so just ignore the 
            // PRESHARP warnings.
#pragma warning suppress 6031, 6523 
            return UnsafeNativeMethods.ReleaseDC(hwnd, hdc); 
        }
 
        internal static int RegisterWindowMessage(string msg)
        {
            int result = SafeNativeMethods.RegisterWindowMessage(msg);
            int lastWin32Error = Marshal.GetLastWin32Error(); 

            if (result == 0) 
            { 
                ThrowWin32ExceptionsIfError(lastWin32Error);
            } 

            return result;
        }
 
        internal static IntPtr SelectObject(IntPtr hdc, IntPtr hObject)
        { 
            // There is no indication in the Windows SDK documentation that SelectObject() 
            // will set an error to be retrieved with GetLastError, so set the pragma to ignore
            // the PRESHARP warning.  Anyway if ReleaseDC() fails here, nothing more can be done 
            // since the code is restoring the orginal object and discarding the temp object.
#pragma warning suppress 6031, 6523
            return UnsafeNativeMethods.SelectObject(hdc, hObject);
        } 

        internal static int SendInput(int inputs, ref NativeMethods.INPUT ki, int size) 
        { 
            int eventCount = UnsafeNativeMethods.SendInput(inputs, ref ki, size);
            int lastWin32Error = Marshal.GetLastWin32Error(); 

            if (eventCount <= 0)
            {
                ThrowWin32ExceptionsIfError(lastWin32Error); 
            }
 
            return eventCount; 
        }
 
        // The Win32 call to SetFocus does not do it for hwnd that are
        // not in the same process as the caller.
        // This is implemented here to work around this behavior.
        // Fake keystroke are sent to a specific hwnd to force 
        // Windows to give the focus to that hwnd.
        static internal bool SetFocus(IntPtr hwnd) 
        { 
            // First Check for ComboLBox
            // Because it uses Keystrokes it dismisses the ComboLBox 
            string className = RealGetWindowClass(hwnd);

            if (className == "ComboLBox")
                return true; 

 
            // If window is currently Disabled or Invisible no need 
            // to continue
            if (!SafeNativeMethods.IsWindowVisible(hwnd) || !SafeNativeMethods.IsWindowEnabled(hwnd)) 
            {
                return false;
            }
 
            // If already focused, leave as-is. Calling SetForegroundWindow
            // on an already focused HWND will remove focus! 
            if (GetFocusedWindow().Equals(hwnd)) 
            {
                return true; 
            }

            // Try calling SetForegroundWindow directly first; it should succeed if we
            // already have the focus or have UIAccess 
            if (UnsafeNativeMethods.SetForegroundWindow(hwnd))
            { 
                return true; 
            }
 
            // Use the hotkey technique:
            // Register a hotkey and send it to ourselves - this gives us the
            // input, and allows us to call SetForegroundWindow.
            short atom = GlobalAddAtom("FocusHotKey"); 
            if (atom == 0)
            { 
                return false; 
            }
            short vk = 0xB9; 
            bool gotHotkey = false;

            for (int tries = 0; tries < 10; tries++)
            { 
                if (RegisterHotKey(IntPtr.Zero, atom, 0, vk))
                { 
                    gotHotkey = true; 
                    break;
                } 

                vk++; // try another key
            }
 
            if (gotHotkey)
            { 
                // Get state of modifiers - and temporarilly release them... 
                bool fShiftDown = (UnsafeNativeMethods.GetAsyncKeyState(UnsafeNativeMethods.VK_SHIFT) & unchecked((int)0x80000000)) != 0;
                bool fAltDown = (UnsafeNativeMethods.GetAsyncKeyState(UnsafeNativeMethods.VK_MENU) & unchecked((int)0x80000000)) != 0; 
                bool fCtrlDown = (UnsafeNativeMethods.GetAsyncKeyState(UnsafeNativeMethods.VK_CONTROL) & unchecked((int)0x80000000)) != 0;

                if (fShiftDown)
                    Input.SendKeyboardInputVK(UnsafeNativeMethods.VK_SHIFT, false); 

                if (fAltDown) 
                    Input.SendKeyboardInputVK(UnsafeNativeMethods.VK_MENU, false); 

                if (fCtrlDown) 
                    Input.SendKeyboardInputVK(UnsafeNativeMethods.VK_CONTROL, false);

                Input.SendKeyboardInputVK(vk, true);
                Input.SendKeyboardInputVK(vk, false); 

                // Restore release modifier keys... 
                if (fShiftDown) 
                    Input.SendKeyboardInputVK(UnsafeNativeMethods.VK_SHIFT, true);
 
                if (fAltDown)
                    Input.SendKeyboardInputVK(UnsafeNativeMethods.VK_MENU, true);

                if (fCtrlDown) 
                    Input.SendKeyboardInputVK(UnsafeNativeMethods.VK_CONTROL, true);
 
                // Spin in this message loop until we get the hot key 
                while (true)
                { 
                    // If the hotkey input gets lost (eg due to desktop switch), GetMessage may not return -
                    // so use MsgWait first so we can timeout if there's no message present instead of blocking.
                    int result = MsgWaitForMultipleObjects(null, false, 2000, NativeMethods.QS_ALLINPUT);
                    if (result == NativeMethods.WAIT_FAILED || result == NativeMethods.WAIT_TIMEOUT) 
                        break;
 
                    NativeMethods.MSG msg = new NativeMethods.MSG(); 
                    if (!GetMessage(ref msg, IntPtr.Zero, 0, 0))
                        break; 

                    // TranslateMessage() will not set an error to be retrieved with GetLastError,
                    // so set the pragma to ignore the PERSHARP warning.
                    // the PERSHARP warning. 
#pragma warning suppress 6031, 6523
                    UnsafeNativeMethods.TranslateMessage(ref msg); 
 
                    // From the Windows SDK documentation:
                    // The return value specifies the value returned by the window procedure. 
                    // Although its meaning depends on the message being dispatched, the return
                    // value generally is ignored.
#pragma warning suppress 6031, 6523
                    UnsafeNativeMethods.DispatchMessage(ref msg); 

                    if (msg.message == NativeMethods.WM_HOTKEY && (short)msg.wParam == atom) 
                    { 
                        break;
                    } 
                }

                UnregisterHotKey(IntPtr.Zero, atom);
            } 

            GlobalDeleteAtom(atom); 
 
            return UnsafeNativeMethods.SetForegroundWindow(hwnd);
        } 

        internal static int SetScrollPos(IntPtr hwnd, int bar, int pos, bool redraw)
        {
            // NOTE: From Windows SDK Documentaion: 
            // If the function succeeds, the return value is the previous position of the scroll
            // box.  If the desktop is themed and the parent window is a message-only window, 
            // the function returns an incorrect value. 

            // The failure case of this API may also be a valid return.  GetLastError() is need to determine a true failure state. 
            // Clear the last error code to make sure we have a good starting condition to determine error state.
            UnsafeNativeMethods.SetLastError(0);
            int prevPos = UnsafeNativeMethods.SetScrollPos(hwnd, bar, pos, redraw);
            int lastWin32Error = Marshal.GetLastWin32Error(); 

            if (prevPos == 0) 
            { 
                ThrowWin32ExceptionsIfError(lastWin32Error);
            } 

            return prevPos;
        }
 
        internal static IntPtr SetWinEventHook(int eventMin, int eventMax, IntPtr hmodWinEventProc, NativeMethods.WinEventProcDef WinEventReentrancyFilter, uint idProcess, uint idThread, int dwFlags)
        { 
            // There is no indication in the Windows SDK documentation that SetWinEventHook() 
            // will set an error to be retrieved with GetLastError, so set the pragma to ignore
            // the PERSHARP warning. 
#pragma warning suppress 6523
            return UnsafeNativeMethods.SetWinEventHook(eventMin, eventMax, hmodWinEventProc, WinEventReentrancyFilter, idProcess, idThread, dwFlags);
        }
 
        // this strips the mnemonic prefix for short cuts as well as leading spaces
        // If we find && leave one & there. 
        internal static string StripMnemonic(string s) 
        {
            // If there are no spaces or & then it's ok just return it 
            if (string.IsNullOrEmpty(s) || s.IndexOfAny(new char[2] { ' ', '&' }) < 0)
            {
                return s;
            } 

            char[] ach = s.ToCharArray(); 
            bool amper = false; 
            bool leadingSpace = false;
            int dest = 0; 

            for (int source = 0; source < ach.Length; source++)
            {
                // get rid of leading spaces 
                if (ach[source] == ' ' && leadingSpace == false)
                { 
                    continue; 
                }
                else 
                {
                    leadingSpace = true;
                }
 
                // get rid of &
                if (ach[source] == '&' && amper == false) 
                { 
                    amper = true;
                } 
                else
                {
                    ach[dest++] = ach[source];
                } 
            }
 
            return new string(ach, 0, dest); 
        }
 
        internal static void ThrowWin32ExceptionsIfError(int errorCode)
        {
            switch (errorCode)
            { 
                case 0:     //    0 ERROR_SUCCESS                   The operation completed successfully.
                    // The error code indicates that there is no error, so do not throw an exception. 
                    break; 

                case 6:     //    6 ERROR_INVALID_HANDLE            The handle is invalid. 
                case 1400:  // 1400 ERROR_INVALID_WINDOW_HANDLE     Invalid window handle.
                case 1401:  // 1401 ERROR_INVALID_MENU_HANDLE       Invalid menu handle.
                case 1402:  // 1402 ERROR_INVALID_CURSOR_HANDLE     Invalid cursor handle.
                case 1403:  // 1403 ERROR_INVALID_ACCEL_HANDLE      Invalid accelerator table handle. 
                case 1404:  // 1404 ERROR_INVALID_HOOK_HANDLE       Invalid hook handle.
                case 1405:  // 1405 ERROR_INVALID_DWP_HANDLE        Invalid handle to a multiple-window position structure. 
                case 1406:  // 1406 ERROR_TLW_WITH_WSCHILD          Cannot create a top-level child window. 
                case 1407:  // 1407 ERROR_CANNOT_FIND_WND_CLASS     Cannot find window class.
                case 1408:  // 1408 ERROR_WINDOW_OF_OTHER_THREAD    Invalid window; it belongs to other thread. 
                    throw new ElementNotAvailableException();

                // We're getting this in AMD64 when calling RealGetWindowClass; adding this code
                // to allow the DRTs to pass while we continue investigation. 
                case 87:    //   87 ERROR_INVALID_PARAMETER
                    throw new ElementNotAvailableException(); 
 
                case 8:     //    8 ERROR_NOT_ENOUGH_MEMORY         Not enough storage is available to process this command.
                case 14:    //   14 ERROR_OUTOFMEMORY               Not enough storage is available to complete this operation. 
                    throw new OutOfMemoryException();

                case 998:   //  998 ERROR_NOACCESS                  Invalid access to memory location.
                case 5:     //    5 ERROR_ACCESS_DENIED 
                    throw new InvalidOperationException();
 
                case 121:   //  121 ERROR_SEM_TIMEOUT               The semaphore timeout period has expired. 
                case 258:   //  258 WAIT_TIMEOUT                    The wait operation timed out.
                case 1053:  // 1053 ERROR_SERVICE_REQUEST_TIMEOUT   The service did not respond to the start or control request in a timely fashion. 
                case 1460:  // 1460 ERROR_TIMEOUT                   This operation returned because the timeout period expired.
                    throw new TimeoutException();

                default: 
                    // Not sure how to map the reset of the error codes so throw generic Win32Exception.
                    throw new Win32Exception(errorCode); 
            } 
        }
 
        internal static bool UnhookWinEvent(IntPtr winEventHook)
        {
            // There is no indication in the Windows SDK documentation that UnhookWinEvent()
            // will set an error to be retrieved with GetLastError, so set the pragma to ignore 
            // the PERSHARP warning.
#pragma warning suppress 6523 
            return UnsafeNativeMethods.UnhookWinEvent(winEventHook); 
        }
 
        internal static bool UnionRect(out NativeMethods.Win32Rect rcDst, ref NativeMethods.Win32Rect rc1, ref NativeMethods.Win32Rect rc2)
        {
            bool result = SafeNativeMethods.UnionRect(out rcDst, ref rc1, ref rc2);
            int lastWin32Error = Marshal.GetLastWin32Error(); 

            if (!result) 
            { 
                ThrowWin32ExceptionsIfError(lastWin32Error);
            } 

            return result;
        }
 
        internal static bool UnregisterHotKey(IntPtr hwnd, short atom)
        { 
            bool result = UnsafeNativeMethods.UnregisterHotKey(hwnd, atom); 
            int lastWin32Error = Marshal.GetLastWin32Error();
 
            if (!result)
            {
                ThrowWin32ExceptionsIfError(lastWin32Error);
            } 

            return result; 
        } 

        internal static IntPtr VirtualAlloc(IntPtr address, UIntPtr size, int allocationType, int protect) 
        {
            IntPtr result = UnsafeNativeMethods.VirtualAlloc(address, size, allocationType, protect);
            int lastWin32Error = Marshal.GetLastWin32Error();
 
            if (result == IntPtr.Zero)
            { 
                ThrowWin32ExceptionsIfError(lastWin32Error); 
            }
 
            return result;
        }

        internal static IntPtr VirtualAllocEx(MS.Internal.AutomationProxies.SafeProcessHandle hProcess, IntPtr address, UIntPtr size, int allocationType, int protect) 
        {
            IntPtr result = UnsafeNativeMethods.VirtualAllocEx(hProcess, address, size, allocationType, protect); 
            int lastWin32Error = Marshal.GetLastWin32Error(); 

            if (result == IntPtr.Zero) 
            {
                ThrowWin32ExceptionsIfError(lastWin32Error);
            }
 
            return result;
        } 
 
        internal static bool VirtualFree(IntPtr address, UIntPtr size, int freeType)
        { 
            bool result = UnsafeNativeMethods.VirtualFree(address, size, freeType);
            int lastWin32Error = Marshal.GetLastWin32Error();

            if (!result) 
            {
                ThrowWin32ExceptionsIfError(lastWin32Error); 
            } 

            return result; 
        }

        internal static bool VirtualFreeEx(MS.Internal.AutomationProxies.SafeProcessHandle hProcess, IntPtr address, UIntPtr size, int freeType)
        { 
            bool result = UnsafeNativeMethods.VirtualFreeEx(hProcess, address, size, freeType);
            int lastWin32Error = Marshal.GetLastWin32Error(); 
 
            if (!result)
            { 
                ThrowWin32ExceptionsIfError(lastWin32Error);
            }

            return result; 
        }
 
        internal static bool WriteProcessMemory(MS.Internal.AutomationProxies.SafeProcessHandle hProcess, IntPtr dest, IntPtr sourceAddress, IntPtr size, out int bytesWritten) 
        {
            bool result = UnsafeNativeMethods.WriteProcessMemory(hProcess, dest, sourceAddress, size, out bytesWritten); 
            int lastWin32Error = Marshal.GetLastWin32Error();

            if (!result)
            { 
                ThrowWin32ExceptionsIfError(lastWin32Error);
            } 
 
            return result;
        } 

        internal static bool IsWindowInGivenProcess(IntPtr hwnd, string targetprocess)
        {
            uint processId; 
            //GetWindowThreadProcessId throws ElementNotAvailableException if the hwnd is no longer valid.
            //But, this exception should be handled by the client accessing this proxy. 
            uint threadId = GetWindowThreadProcessId(hwnd, out processId); 
            try
            { 
                string processName = System.Diagnostics.Process.GetProcessById((int)processId).ProcessName;
                if (processName == targetprocess)
                {
                    return true; 
                }
            } 
            catch (Exception ex) 
            {
                if (IsCriticalException(ex)) 
                    throw;

                if (ex is ArgumentException || ex is SystemException)
                { 
                    //The process is no longer running which implies AutomationElement is no longer available.
                    //Let the client handle it. 
                    throw new ElementNotAvailableException(); 
                }
 
                //All other exceptions are ignored as the purpose of this method is to find whether the hwnd belongs to
                //a particular process or not.
            }
            return false; 
        }
 
        internal static bool InTheShellProcess(IntPtr hwnd) 
        {
            IntPtr hwndShell = SafeNativeMethods.GetShellWindow(); 
            if (hwndShell == IntPtr.Zero)
                return false;
            uint idProcessUs;
            GetWindowThreadProcessId(hwnd, out idProcessUs); 
            uint idProcessShell;
            GetWindowThreadProcessId(hwndShell, out idProcessShell); 
            return idProcessUs == idProcessShell; 
        }
 
        // the windows listview has feature (like group by) in v6 that only exist on
        // vista and beyond.  This lets us test for that.
        internal static bool IsComctrlV6OnOsVerV6orHigher(IntPtr hwnd)
        { 
            int commonControlVersion  = Misc.ProxySendMessageInt(hwnd, NativeMethods.CCM_GETVERSION, IntPtr.Zero, IntPtr.Zero);
            if (Environment.OSVersion.Version.Major >= 6 && commonControlVersion >= 6) 
            { 
                return true;
            } 

            return false;
        }
 
        #endregion
 
        // ------------------------------------------------------ 
        //
        // Internal Fields 
        //
        // ------------------------------------------------------

        #region Internal Fields 

        // Max length for the name 
        internal const int MaxLengthNameProperty = 2000; 

        // Timeout for clearing menus 
        internal const long MenuTimeOut = 100;

        #endregion
 
        // -----------------------------------------------------
        // 
        // Private Methods 
        //
        // ------------------------------------------------------ 

        #region Private Methods

        private static bool EnumToolTipWindows(IntPtr hwnd, ref UnsafeNativeMethods.ENUMTOOLTIPWINDOWINFO lParam) 
        {
            // Use ProxyGetClassName here instead of GetClassName(), 
            // since for a winforms tooltip the latter will return 
            // "WindowsForms10.tooltips_class32.app.0.b7ab7b".
            // Instead, ProxyGetClassName uses WM_GETOBJECT with 
            // OBJID_QUERYCLASSNAMEIDX, which will return the correct answer.
            if (!ProxyGetClassName(hwnd).Equals("tooltips_class32"))
            {
                return true; 
            }
 
            NativeMethods.TOOLINFO tool = new NativeMethods.TOOLINFO(); 
            tool.Init(Marshal.SizeOf(typeof(NativeMethods.TOOLINFO)));
            // For tooltips with ids of 0, MFC will create the tooltip with the flag of TTF_IDISHWND. 
            // TTF_IDISHWND indicates that the uId member is the window handle to the tool.
            if (lParam.id == 0)
            {
                tool.hwnd = Misc.GetParent(lParam.hwnd); 
                tool.uId = unchecked((int)lParam.hwnd);
                tool.uFlags = NativeMethods.TTF_IDISHWND; 
            } 
            else
            { 
                tool.hwnd = lParam.hwnd;
                tool.uId = lParam.id;
            }
 
            string name = XSendMessage.GetItemText(hwnd, tool);
 
            // Didn't get anything - continue looking... 
            if (string.IsNullOrEmpty(name))
            { 
                return true;
            }

            lParam.name = name; 

            // Got it - can stop iterating now. 
            return false; 
        }
 
        // Get the size of a page in memory for VirtualAlloc
        private static uint GetPageSize()
        {
            NativeMethods.SYSTEM_INFO sysInfo; 
            UnsafeNativeMethods.GetSystemInfo(out sysInfo);
            return sysInfo.dwPageSize; 
        } 

        //This function throws corresponding exception depending on the last error. 
        private static void EvaluateSendMessageTimeoutError(int error)
        {
            EvaluateSendMessageTimeoutError(error, false);
        } 

        private static void EvaluateSendMessageTimeoutError(int error, bool ignoreTimeout) 
        { 
            // SendMessageTimeout Function
            // If the function fails or times out, the return value is zero. To get extended error information, 
            // call GetLastError. If GetLastError returns zero, then the function timed out.
            // NOTE: The GetLastError after a SendMessageTimeout my also be an ERROR_TIMEOUT depending on the
            // message.
 
            // 1460 This operation returned because the timeout period expired. ERROR_TIMEOUT
            if (error == 0 || error == 1460) 
            { 
                if (!ignoreTimeout)
                { 
                    throw new TimeoutException();
                }
            }
            else 
            {
                ThrowWin32ExceptionsIfError(error); 
            } 
        }
 
        private static Rect[] GetTitlebarRectsXP(IntPtr hwnd)
        {
            Debug.Assert(System.Environment.OSVersion.Version.Major < 6);
 
            UnsafeNativeMethods.TITLEBARINFO tiDL;
            if (!Misc.ProxyGetTitleBarInfo(hwnd, out tiDL)) 
            { 
                return null;
            } 

            // Titlebars that are invisible or may not exist should not have a rect
            if ((tiDL.rgstate[NativeMethods.INDEX_TITLEBAR_SELF] & (NativeMethods.STATE_SYSTEM_INVISIBLE | NativeMethods.STATE_SYSTEM_OFFSCREEN)) != 0)
            { 
                return null;
            } 
 
            // We really should be using the the theme APIs but they give incorrect results with the titlebar buttons so we are reverting back to system metrics
            // This is not perfect, its a looks like it may be a few pixels of here or there but clicking on the center of the button will be sucessfull.  The only place this 
            // does not work is on console windows when the theme is Windows Clasic Style.

            // The system metric seems to be just bit off, subtracting 1 seems to get a better result on all themes
            int buttonWidth = UnsafeNativeMethods.GetSystemMetrics(NativeMethods.SM_CXSIZE) - 1; 
            int buttonHeight = UnsafeNativeMethods.GetSystemMetrics(NativeMethods.SM_CYSIZE) - 1;
 
            Rect[] rects = new Rect[NativeMethods.CCHILDREN_TITLEBAR + 1]; 

            // Start at the end and work backwards to the system menu.  Subtract buttonSize when a child is present. 
            int leftEdge;

            if (Misc.IsLayoutRTL(hwnd))
            { 
                // Right to left mirroring style
 
                // This is to take in count for a bug in GetTitleBarInfo().  It does not calculate the 
                // rcTitleBar correctly when the WS_EX_LAYOUTRTL extended style is set.  It assumes
                // SYSMENU is always on the left and removes its space from the wrong side of rcTitleBar. 
                // Use the bounding rectangle of the whole title bar to get the true left boundary.
                leftEdge = (int)(Misc.GetTitleBarRect(hwnd).Left);
                for (int i = NativeMethods.INDEX_TITLEBAR_MAC; i > NativeMethods.INDEX_TITLEBAR_SELF; i--)
                { 
                    if ((tiDL.rgstate[i] & NativeMethods.STATE_SYSTEM_INVISIBLE) == 0)
                    { 
                        rects[i] = new Rect(leftEdge, tiDL.rcTitleBar.top, buttonWidth, buttonHeight); 
                        leftEdge += buttonWidth;
                    } 
                    else
                    {
                        rects[i] = Rect.Empty;
                    } 
                }
            } 
            else 
            {
                leftEdge = tiDL.rcTitleBar.right - buttonWidth; 
                for (int i = NativeMethods.INDEX_TITLEBAR_MAC; i > NativeMethods.INDEX_TITLEBAR_SELF; i--)
                {
                    if ((tiDL.rgstate[i] & NativeMethods.STATE_SYSTEM_INVISIBLE) == 0)
                    { 
                        rects[i] = new Rect(leftEdge, tiDL.rcTitleBar.top, buttonWidth, buttonHeight);
                        leftEdge -= buttonWidth; 
                    } 
                    else
                    { 
                        rects[i] = Rect.Empty;
                    }
                }
            } 

            return rects; 
        } 

        private static Rect[] GetTitlebarRectsEx(IntPtr hwnd) 
        {
            Debug.Assert(System.Environment.OSVersion.Version.Major >= 6);

            UnsafeNativeMethods.TITLEBARINFOEX ti; 
            if (!Misc.ProxyGetTitleBarInfoEx(hwnd, out ti))
            { 
                return null; 
            }
 
            // Titlebars that are invisible or may not exist should not have a rect
            if ((ti.rgstate[NativeMethods.INDEX_TITLEBAR_SELF] & (NativeMethods.STATE_SYSTEM_INVISIBLE | NativeMethods.STATE_SYSTEM_OFFSCREEN)) != 0)
            {
                return null; 
            }
 
            Rect[] rects = new Rect[NativeMethods.CCHILDREN_TITLEBAR + 1]; 
            for (int i = 0; i <= NativeMethods.CCHILDREN_TITLEBAR; i++)
            { 
                // Buttons that are invisible or may not exist should not have a rect
                if ((ti.rgstate[i] & NativeMethods.STATE_SYSTEM_INVISIBLE) != 0)
                {
                    rects[i] = Rect.Empty; 
                }
                else 
                { 
                    rects[i] = new Rect(ti.rgrect[i].left, ti.rgrect[i].top, ti.rgrect[i].right - ti.rgrect[i].left, ti.rgrect[i].bottom - ti.rgrect[i].top);
                } 
            }

            return rects;
        } 

        #endregion 
 
        // -----------------------------------------------------
        // 
        // Private Fields
        //
        // -----------------------------------------------------
 
        #region Private Fields
 
        // Generic flags for SendMessages 
        private const int _sendMessageFlags = NativeMethods.SMTO_BLOCK;
 
        // Generic time out for SendMessages
        // Most messages won't need anything near this - but there are a few - eg. WM_COMMAND/CBN_DROPDOWN
        // when sent to IE's address combo for the first time causes it to populate iself, and that can
        // take a couple of seconds on a slow machine. 
        private const int _sendMessageTimeoutValue = 10000;
 
        // Array of known class names 
        private static string[] _asClassNames = {
            "ListBox", 
            "#32768",
            "Button",
            "Static",
            "Edit", 
            "ComboBox",
            "#32770", 
            "#32771", 
            "MDIClient",
            "#32769", 
            "ScrollBar",
            "msctls_statusbar32",
            "ToolbarWindow32",
            "msctls_progress32", 
            "SysAnimate32",
            "SysTabControl32", 
            "msctls_hotkey32", 
            "SysHeader32",
            "msctls_trackbar32", 
            "SysListView32",
            "OpenListView",
            "msctls_updown",
            "msctls_updown32", 
            "tooltips_class",
            "tooltips_class32", 
            "SysTreeView32", 
            "SysMonthCal32",
            "SysDateTimePick32", 
            "RICHEDIT",
            "RichEdit20A",
            "RichEdit20W",
            "SysIPAddress32" 
        };
 
        #endregion 

    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK