File: misc\GDI\UnsafeNativeMethods.cs
Project: ndp\fx\src\System.Windows.Forms.csproj (System.Windows.Forms)
//------------------------------------------------------------------------------
// <copyright file="UnsafeNativeMethods.cs" company="Microsoft">
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// </copyright>                                                                
//------------------------------------------------------------------------------
 
 
#if Microsoft_NAMESPACE
namespace System.Windows.Forms.Internal
#elif DRAWING_NAMESPACE
namespace System.Drawing.Internal
#else
namespace System.Experimental.Gdi
#endif
{
    using System;
    using System.Internal;
    using System.Runtime.InteropServices;
    using System.Security.Permissions;
    using System.Collections;
    using System.IO;
    using System.Text;
    using System.Diagnostics.CodeAnalysis;
    using System.Drawing;
    using System.Diagnostics;
    using System.Runtime.Versioning;
    [
    System.Security.SuppressUnmanagedCodeSecurityAttribute()
    ]
#if Microsoft_PUBLIC_GRAPHICS_LIBRARY
    public
#else
    internal
#endif
    static partial class IntUnsafeNativeMethods 
    {
        [DllImport(ExternDll.User32, SetLastError=true, ExactSpelling=true, EntryPoint="GetDC", CharSet=System.Runtime.InteropServices.CharSet.Auto)]
        [ResourceExposure(ResourceScope.Process)]
        public static extern IntPtr IntGetDC(HandleRef hWnd);
        [ResourceExposure(ResourceScope.Process)]
        [ResourceConsumption(ResourceScope.Process)]
        public static IntPtr GetDC(HandleRef hWnd) {
            IntPtr hdc = System.Internal.HandleCollector.Add(IntGetDC(hWnd), IntSafeNativeMethods.CommonHandles.HDC);
            DbgUtil.AssertWin32(hdc != IntPtr.Zero, "GetHdc([hWnd=0x{0:X8}]) failed.", hWnd);
            return hdc;
        }
 
        /// <devdoc>
        ///     NOTE: DeleteDC is to be used to delete the hdc created from CreateCompatibleDC ONLY.  All other hdcs should be
        ///     deleted with DeleteHDC.
        /// </devdoc>
        [DllImport(ExternDll.Gdi32, SetLastError = true, ExactSpelling = true, EntryPoint = "DeleteDC", CharSet = CharSet.Auto)]
        [ResourceExposure(ResourceScope.None)]
        public static extern bool IntDeleteDC(HandleRef hDC);
        public static bool DeleteDC(HandleRef hDC) {
            System.Internal.HandleCollector.Remove((IntPtr)hDC, IntSafeNativeMethods.CommonHandles.GDI);
            bool retVal = IntDeleteDC(hDC);
            DbgUtil.AssertWin32(retVal, "DeleteDC([hdc=0x{0:X8}]) failed.", hDC.Handle);
            return retVal;
        }
        public static bool DeleteHDC(HandleRef hDC) {
            System.Internal.HandleCollector.Remove((IntPtr)hDC, IntSafeNativeMethods.CommonHandles.HDC);
            bool retVal = IntDeleteDC(hDC);
            DbgUtil.AssertWin32(retVal, "DeleteHDC([hdc=0x{0:X8}]) failed.", hDC.Handle);
            return retVal;
        }
 
        [DllImport(ExternDll.User32, SetLastError=true, ExactSpelling=true, EntryPoint="ReleaseDC", CharSet=System.Runtime.InteropServices.CharSet.Auto)]
        [ResourceExposure(ResourceScope.None)]
        public static extern int IntReleaseDC(HandleRef hWnd, HandleRef hDC);
        public static int ReleaseDC(HandleRef hWnd, HandleRef hDC) {
            System.Internal.HandleCollector.Remove((IntPtr)hDC, IntSafeNativeMethods.CommonHandles.HDC);
            // Note: retVal == 0 means it was not released but doesn't necessarily means an error; class or private DCs are never released.
            return IntReleaseDC(hWnd, hDC);
        }
 
        // SECREVIEW : This method is called internally only and passed in safe data (obtain from the system).
        [SuppressMessage("Microsoft.Security", "CA2101:SpecifyMarshalingForPInvokeStringArguments")]
        [DllImport(ExternDll.Gdi32, SetLastError=true, EntryPoint="CreateDC", CharSet=System.Runtime.InteropServices.CharSet.Auto)]
        [ResourceExposure(ResourceScope.Process)]
        public static extern IntPtr IntCreateDC(string lpszDriverName, string lpszDeviceName, string lpszOutput, HandleRef /*DEVMODE*/ lpInitData);
        [ResourceExposure(ResourceScope.Process)]
        [ResourceConsumption(ResourceScope.Process)]
        public static IntPtr CreateDC(String lpszDriverName, string lpszDeviceName, string lpszOutput, HandleRef /*DEVMODE*/ lpInitData) 
        {
            IntPtr hdc = System.Internal.HandleCollector.Add(IntCreateDC(lpszDriverName, lpszDeviceName, lpszOutput, lpInitData), IntSafeNativeMethods.CommonHandles.HDC);
            DbgUtil.AssertWin32(hdc != IntPtr.Zero, "CreateDC([driverName={0}], [deviceName={1}], [fileName={2}], [devMode={3}]) failed.", lpszDriverName, lpszDeviceName, lpszOutput, lpInitData.Handle);
            return hdc;
        }
 
        // SECREVIEW : This method is called internally only and passed in safe data (obtain from the system).
        [SuppressMessage("Microsoft.Security", "CA2101:SpecifyMarshalingForPInvokeStringArguments")]
        [DllImport(ExternDll.Gdi32, SetLastError=true, EntryPoint="CreateIC", CharSet=System.Runtime.InteropServices.CharSet.Auto)]
        [ResourceExposure(ResourceScope.Process)]
        public static extern IntPtr IntCreateIC(string lpszDriverName, string lpszDeviceName, string lpszOutput, HandleRef /*DEVMODE*/ lpInitData);
        [ResourceExposure(ResourceScope.Process)]
        [ResourceConsumption(ResourceScope.Process)]
        public static IntPtr CreateIC(string lpszDriverName, string lpszDeviceName, string lpszOutput, HandleRef /*DEVMODE*/ lpInitData) 
        {
            IntPtr hdc = System.Internal.HandleCollector.Add(IntCreateIC(lpszDriverName, lpszDeviceName, lpszOutput, lpInitData), IntSafeNativeMethods.CommonHandles.HDC);
            DbgUtil.AssertWin32(hdc != IntPtr.Zero, "CreateIC([driverName={0}], [deviceName={1}], [fileName={2}], [devMode={3}]) failed.", lpszDriverName, lpszDeviceName, lpszOutput, lpInitData.Handle);
            return hdc;
        }
 
        /// <devdoc>
        ///     CreateCompatibleDC requires to add a GDI handle instead of an HDC handle to avoid perf penalty in HandleCollector.
        ///     The hdc obtained from this method needs to be deleted with DeleteDC instead of DeleteHDC.
        /// </devdoc>
        [DllImport(ExternDll.Gdi32, SetLastError = true, ExactSpelling = true, EntryPoint = "CreateCompatibleDC", CharSet = CharSet.Auto)]
        [ResourceExposure(ResourceScope.Process)]
        public static extern IntPtr IntCreateCompatibleDC(HandleRef hDC);
        [ResourceExposure(ResourceScope.Process)]
        [ResourceConsumption(ResourceScope.Process)]
        public static IntPtr CreateCompatibleDC(HandleRef hDC)
        {
            IntPtr compatibleDc = System.Internal.HandleCollector.Add(IntCreateCompatibleDC(hDC), IntSafeNativeMethods.CommonHandles.GDI);
            DbgUtil.AssertWin32(compatibleDc != IntPtr.Zero, "CreateCompatibleDC([hdc=0x{0:X8}]) failed", hDC.Handle);
            return compatibleDc;
        }
 
 
        [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling=true, EntryPoint="SaveDC", CharSet=System.Runtime.InteropServices.CharSet.Auto)]
        [ResourceExposure(ResourceScope.None)]
        public static extern int IntSaveDC(HandleRef hDC);
        public static int SaveDC(HandleRef hDC)
        {
            int state = IntSaveDC(hDC);
            DbgUtil.AssertWin32(state != 0, "SaveDC([hdc=0x{0:X8}]) failed", hDC.Handle);
            return state;
        }
        
        [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling=true, EntryPoint="RestoreDC", CharSet=System.Runtime.InteropServices.CharSet.Auto)]
        [ResourceExposure(ResourceScope.None)]
        public static extern bool IntRestoreDC(HandleRef hDC, int nSavedDC);        
        public static bool RestoreDC(HandleRef hDC, int nSavedDC)
        {
            bool retVal = IntRestoreDC( hDC, nSavedDC );
            // 
 
 
 
            return retVal;
        }
        
        [DllImport(ExternDll.User32, SetLastError=true, ExactSpelling = true)]
        [ResourceExposure(ResourceScope.Process)]
        public static extern IntPtr WindowFromDC(HandleRef hDC);
 
        [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling=true, CharSet=CharSet.Auto)]
        [ResourceExposure(ResourceScope.None)]
        public static extern int GetDeviceCaps(HandleRef hDC, int nIndex);
 
        [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling=true, EntryPoint="OffsetViewportOrgEx", CharSet=System.Runtime.InteropServices.CharSet.Auto)]
        [ResourceExposure(ResourceScope.None)]
        public static extern bool IntOffsetViewportOrgEx(HandleRef hDC, int nXOffset, int nYOffset, [In, Out] IntNativeMethods.POINT point);
        public static bool OffsetViewportOrgEx(HandleRef hDC, int nXOffset, int nYOffset, [In, Out] IntNativeMethods.POINT point)
        {
            bool retVal = IntOffsetViewportOrgEx(hDC, nXOffset, nYOffset, point);
            DbgUtil.AssertWin32(retVal, "OffsetViewportOrgEx([hdc=0x{0:X8}], dx=[{1}], dy=[{2}], [out pPoint]) failed.", hDC.Handle, nXOffset, nYOffset);
            return retVal;
        }
 
        [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling=true, EntryPoint="SetGraphicsMode", CharSet=System.Runtime.InteropServices.CharSet.Auto)]
        [ResourceExposure(ResourceScope.None)]
        public static extern int IntSetGraphicsMode(HandleRef hDC, int iMode);
        public static int SetGraphicsMode(HandleRef hDC, int iMode)
        {
            iMode = IntSetGraphicsMode(hDC, iMode);
            DbgUtil.AssertWin32(iMode != 0, "SetGraphicsMode([hdc=0x{0:X8}], [GM_ADVANCED]) failed.", hDC.Handle);
            return iMode;
        }
 
        [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling=true, CharSet=System.Runtime.InteropServices.CharSet.Auto)]
        [ResourceExposure(ResourceScope.None)]
        public static extern int GetGraphicsMode(HandleRef hDC);
 
        [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling=true)]
        [ResourceExposure(ResourceScope.None)]
        public static extern int GetROP2(HandleRef hdc);
 
        [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling = true, CharSet = System.Runtime.InteropServices.CharSet.Auto)]
        [ResourceExposure(ResourceScope.None)]
        public static extern int SetROP2(HandleRef hDC, int nDrawMode);
 
 
        // Region.
        [DllImport(ExternDll.Gdi32, SetLastError = true, ExactSpelling = true, EntryPoint = "CombineRgn", CharSet = System.Runtime.InteropServices.CharSet.Auto)]
        [ResourceExposure(ResourceScope.None)]
        public static extern IntNativeMethods.RegionFlags IntCombineRgn(HandleRef hRgnDest, HandleRef hRgnSrc1, HandleRef hRgnSrc2, RegionCombineMode combineMode);
        public static IntNativeMethods.RegionFlags CombineRgn(HandleRef hRgnDest, HandleRef hRgnSrc1, HandleRef hRgnSrc2, RegionCombineMode combineMode) {
            Debug.Assert(hRgnDest.Wrapper != null && hRgnDest.Handle != IntPtr.Zero, "Destination region is invalid");
            Debug.Assert(hRgnSrc1.Wrapper != null && hRgnSrc1.Handle != IntPtr.Zero, "Source region 1 is invalid");
            Debug.Assert(hRgnSrc2.Wrapper != null && hRgnSrc2.Handle != IntPtr.Zero, "Source region 2 is invalid");
 
            if (hRgnDest.Wrapper == null || hRgnSrc1.Wrapper == null || hRgnSrc2.Wrapper == null) {
                return IntNativeMethods.RegionFlags.ERROR;
            }
 
            // Note: CombineRgn can return Error when no regions are combined, this is not an error condition.
            return IntCombineRgn(hRgnDest, hRgnSrc1, hRgnSrc2, combineMode);
        }
 
        [DllImport(ExternDll.Gdi32, SetLastError = true, ExactSpelling = true, EntryPoint = "GetClipRgn", CharSet = System.Runtime.InteropServices.CharSet.Auto)]
        [ResourceExposure(ResourceScope.None)]
        public static extern int IntGetClipRgn(HandleRef hDC, HandleRef hRgn);
        public static int GetClipRgn(HandleRef hDC, HandleRef hRgn) {
            int retVal = IntGetClipRgn(hDC, hRgn);
            DbgUtil.AssertWin32(retVal != -1, "IntGetClipRgn([hdc=0x{0:X8}], [hRgn]) failed.", hDC.Handle);
            return retVal;
        }
 
        [DllImport(ExternDll.Gdi32, SetLastError = true, ExactSpelling = true, EntryPoint = "SelectClipRgn", CharSet = System.Runtime.InteropServices.CharSet.Auto)]
        [ResourceExposure(ResourceScope.None)]
        public static extern IntNativeMethods.RegionFlags IntSelectClipRgn(HandleRef hDC, HandleRef hRgn);
        public static IntNativeMethods.RegionFlags SelectClipRgn(HandleRef hDC, HandleRef hRgn)
        {
            IntNativeMethods.RegionFlags result = IntSelectClipRgn(hDC, hRgn);
            DbgUtil.AssertWin32(result != IntNativeMethods.RegionFlags.ERROR, "SelectClipRgn([hdc=0x{0:X8}], [hRegion=0x{1:X8}]) failed.", hDC.Handle, hRgn.Handle);
            return result;
        }
 
        [DllImport(ExternDll.Gdi32, SetLastError = true, ExactSpelling = true, EntryPoint = "GetRgnBox", CharSet = System.Runtime.InteropServices.CharSet.Auto)]
        [ResourceExposure(ResourceScope.None)]
        public static extern IntNativeMethods.RegionFlags IntGetRgnBox(HandleRef hRgn, [In, Out] ref IntNativeMethods.RECT clipRect);
        public static IntNativeMethods.RegionFlags GetRgnBox(HandleRef hRgn, [In, Out] ref IntNativeMethods.RECT clipRect)
        {
            IntNativeMethods.RegionFlags result = IntGetRgnBox(hRgn, ref clipRect);
            DbgUtil.AssertWin32(result != IntNativeMethods.RegionFlags.ERROR, "GetRgnBox([hRegion=0x{0:X8}], [out rect]) failed.", hRgn.Handle);
            return result;
        }
 
        // Font.
 
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2118:ReviewSuppressUnmanagedCodeSecurityUsage")]
        [DllImport(ExternDll.Gdi32, SetLastError = true, EntryPoint = "CreateFontIndirect", CharSet = System.Runtime.InteropServices.CharSet.Auto)]
        [ResourceExposure(ResourceScope.Process)]
        public static extern IntPtr IntCreateFontIndirect([In, Out, MarshalAs(UnmanagedType.AsAny)] object lf); // need object here since LOGFONT is not public.
        [ResourceExposure(ResourceScope.Process)]
        [ResourceConsumption(ResourceScope.Process)]
        public static IntPtr CreateFontIndirect(/*IntNativeMethods.LOGFONT*/ object lf) 
        {
            IntPtr hFont = System.Internal.HandleCollector.Add(IntCreateFontIndirect(lf), IntSafeNativeMethods.CommonHandles.GDI);
            DbgUtil.AssertWin32(hFont != IntPtr.Zero, "CreateFontIndirect(logFont) failed.");
            return hFont;
        }
 
        // Common.
        [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling = true, EntryPoint = "DeleteObject", CharSet = System.Runtime.InteropServices.CharSet.Auto)]
        [ResourceExposure(ResourceScope.None)]
        public static extern bool IntDeleteObject(HandleRef hObject);
        public static bool DeleteObject(HandleRef hObject)
        {
            System.Internal.HandleCollector.Remove((IntPtr)hObject, IntSafeNativeMethods.CommonHandles.GDI);
            bool retVal = IntDeleteObject(hObject);
            DbgUtil.AssertWin32(retVal, "DeleteObject(hObj=[0x{0:X8}]) failed.", hObject.Handle);
            return retVal;
        }
 
        [DllImport(ExternDll.Gdi32, SetLastError=true, EntryPoint = "GetObject", ExactSpelling=false, CharSet=System.Runtime.InteropServices.CharSet.Auto)]
        [ResourceExposure(ResourceScope.None)]
        public static extern int IntGetObject(HandleRef hBrush, int nSize, [In, Out] IntNativeMethods.LOGBRUSH lb);
        public static int GetObject(HandleRef hBrush, IntNativeMethods.LOGBRUSH lb) 
        {
            int retVal = IntGetObject(hBrush, System.Runtime.InteropServices.Marshal.SizeOf(typeof(IntNativeMethods.LOGBRUSH)), lb);
            DbgUtil.AssertWin32(retVal != 0, "GetObject(hObj=[0x{0:X8}], [LOGBRUSH]) failed.", hBrush.Handle);
            return retVal;
        }
        
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2101:SpecifyMarshalingForPInvokeStringArguments")]
        [DllImport(ExternDll.Gdi32, SetLastError=true, EntryPoint = "GetObject", ExactSpelling=false, CharSet=System.Runtime.InteropServices.CharSet.Auto)]
        [ResourceExposure(ResourceScope.None)]
        public static extern int IntGetObject(HandleRef hFont, int nSize, [In, Out] IntNativeMethods.LOGFONT lf);
        public static int GetObject(HandleRef hFont, IntNativeMethods.LOGFONT lp) 
        {
            int retVal = IntGetObject(hFont, System.Runtime.InteropServices.Marshal.SizeOf(typeof(IntNativeMethods.LOGFONT)), lp);
            DbgUtil.AssertWin32(retVal != 0, "GetObject(hObj=[0x{0:X8}], [LOGFONT]) failed.", hFont.Handle);
            return retVal;
        }
 
        [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling=true, EntryPoint="SelectObject", CharSet=CharSet.Auto)]
        [ResourceExposure(ResourceScope.Process)]
        public static extern IntPtr IntSelectObject(HandleRef hdc, HandleRef obj);
        [ResourceExposure(ResourceScope.Process)]
        [ResourceConsumption(ResourceScope.Process)]
        public static IntPtr SelectObject(HandleRef hdc, HandleRef obj)
        {
            IntPtr oldObj = IntSelectObject(hdc, obj);
            DbgUtil.AssertWin32(oldObj != IntPtr.Zero, "SelectObject(hdc=hObj=[0x{0:X8}], hObj=[0x{1:X8}]) failed.", hdc.Handle, obj.Handle);
            return oldObj;
        }
                       
        [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling = true, EntryPoint="GetCurrentObject", CharSet = System.Runtime.InteropServices.CharSet.Auto)]
        [ResourceExposure(ResourceScope.Process)]
        public static extern IntPtr IntGetCurrentObject(HandleRef hDC, int uObjectType);
        [ResourceExposure(ResourceScope.Process)]
        [ResourceConsumption(ResourceScope.Process)]
        public static IntPtr GetCurrentObject(HandleRef hDC, int uObjectType)
        {
            IntPtr hGdiObj = IntGetCurrentObject(hDC, uObjectType);
            // If the selected object is a region the return value is HGI_ERROR on failure.
            DbgUtil.AssertWin32(hGdiObj != IntPtr.Zero, "GetObject(hdc=[0x{0:X8}], type=[{1}]) failed.", hDC, uObjectType );
            return hGdiObj;
        }
 
        [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling=true, EntryPoint="GetStockObject", CharSet=CharSet.Auto)]
        [ResourceExposure(ResourceScope.Process)]
        public static extern IntPtr IntGetStockObject(int nIndex);
        [ResourceExposure(ResourceScope.Process)]
        [ResourceConsumption(ResourceScope.Process)]
        public static IntPtr GetStockObject(int nIndex)
        {
            IntPtr hGdiObj = IntGetStockObject(nIndex);
            DbgUtil.AssertWin32(hGdiObj != IntPtr.Zero, "GetStockObject({0}) failed.", nIndex );
            return hGdiObj;
        }
 
 
        // Drawing.
 
        [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling=true, CharSet=System.Runtime.InteropServices.CharSet.Auto)]
        [ResourceExposure(ResourceScope.None)]
        public static extern int GetNearestColor(HandleRef hDC, int color);
 
        [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling = true, CharSet = System.Runtime.InteropServices.CharSet.Auto)]
        [ResourceExposure(ResourceScope.None)]
        public static extern int /*COLORREF*/ SetTextColor(HandleRef hDC, int crColor);
 
        [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling = true, CharSet = System.Runtime.InteropServices.CharSet.Auto)]
        [ResourceExposure(ResourceScope.None)]
        public static extern int GetTextAlign(HandleRef hdc);
 
        [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling = true, CharSet = System.Runtime.InteropServices.CharSet.Auto)]
        [ResourceExposure(ResourceScope.None)]
        public static extern int /*COLORREF*/ GetTextColor(HandleRef hDC);
 
        [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling = true, CharSet = System.Runtime.InteropServices.CharSet.Auto)]
        [ResourceExposure(ResourceScope.None)]
        public static extern int SetBkColor(HandleRef hDC, int clr);
 
        [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling = true, EntryPoint="SetBkMode", CharSet = System.Runtime.InteropServices.CharSet.Auto)]
        [ResourceExposure(ResourceScope.None)]
        public static extern int IntSetBkMode(HandleRef hDC, int nBkMode);
        public static int SetBkMode(HandleRef hDC, int nBkMode)
        {
            int oldMode = IntSetBkMode( hDC, nBkMode );
            DbgUtil.AssertWin32(oldMode != 0, "SetBkMode(hdc=[0x{0:X8}], Mode=[{1}]) failed.", hDC.Handle, nBkMode );
            return oldMode;
        }
 
        [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling = true, EntryPoint="GetBkMode", CharSet = System.Runtime.InteropServices.CharSet.Auto)]
        [ResourceExposure(ResourceScope.None)]
        public static extern int IntGetBkMode(HandleRef hDC);
        public static int GetBkMode(HandleRef hDC)
        {
            int mode = IntGetBkMode( hDC );
            DbgUtil.AssertWin32(mode != 0, "GetBkMode(hdc=[0x{0:X8}]) failed.", hDC.Handle);
            return mode;
        }
 
        [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling = true, CharSet = System.Runtime.InteropServices.CharSet.Auto)]
        [ResourceExposure(ResourceScope.None)]
        public static extern int GetBkColor(HandleRef hDC);
 
 
        [DllImport( ExternDll.User32, SetLastError = true, ExactSpelling = true, CharSet = System.Runtime.InteropServices.CharSet.Unicode )]
        [ResourceExposure(ResourceScope.None)]
        public static extern int DrawTextW(HandleRef hDC, string lpszString, int nCount, ref IntNativeMethods.RECT lpRect, int nFormat);
 
        [DllImport( ExternDll.User32, SetLastError = true, ExactSpelling = true, CharSet = System.Runtime.InteropServices.CharSet.Ansi )]
        [ResourceExposure(ResourceScope.None)]
        public static extern int DrawTextA(HandleRef hDC, byte[] lpszString, int byteCount, ref IntNativeMethods.RECT lpRect, int nFormat);
 
        public static int DrawText( HandleRef hDC, string text, ref IntNativeMethods.RECT lpRect, int nFormat )
        {
            int retVal;
            if( Marshal.SystemDefaultCharSize == 1 )
            {
                // CapRectangleForWin9x(ref lpRect);
                // we have to do this because if we pass too big of a value (<= 2^31) to win9x
                // it fails and returns negative values as the rect in which it painted the text
                lpRect.top = Math.Min( Int16.MaxValue, lpRect.top );
                lpRect.left = Math.Min( Int16.MaxValue, lpRect.left );
                lpRect.right = Math.Min( Int16.MaxValue, lpRect.right );
                lpRect.bottom = Math.Min( Int16.MaxValue, lpRect.bottom );
 
                // Convert Unicode string to ANSI.
                int byteCount = IntUnsafeNativeMethods.WideCharToMultiByte( IntNativeMethods.CP_ACP, 0, text, text.Length, null, 0, IntPtr.Zero, IntPtr.Zero );
                byte[] textBytes = new byte[byteCount];
                IntUnsafeNativeMethods.WideCharToMultiByte( IntNativeMethods.CP_ACP, 0, text, text.Length, textBytes, textBytes.Length, IntPtr.Zero, IntPtr.Zero );
 
                // Security: Windows 95/98/Me: This value may not exceed 8192.
                byteCount = Math.Min( byteCount, IntNativeMethods.MaxTextLengthInWin9x );
                retVal = DrawTextA( hDC, textBytes, byteCount, ref lpRect, nFormat );
            }
            else
            {
                retVal = DrawTextW( hDC, text, text.Length, ref lpRect, nFormat );
            }
 
            DbgUtil.AssertWin32( retVal != 0, "DrawText(hdc=[0x{0:X8}], text=[{1}], rect=[{2}], flags=[{3}] failed.", hDC.Handle, text, lpRect, nFormat );
            return retVal;
        }
 
        [DllImport(ExternDll.User32, SetLastError=true, CharSet=System.Runtime.InteropServices.CharSet.Unicode)]
        [ResourceExposure(ResourceScope.None)]
        public static extern int DrawTextExW(HandleRef hDC, string lpszString, int nCount, ref IntNativeMethods.RECT lpRect, int nFormat, [In, Out] IntNativeMethods.DRAWTEXTPARAMS lpDTParams);
 
        [DllImport(ExternDll.User32, SetLastError=true, CharSet=System.Runtime.InteropServices.CharSet.Ansi)]
        [ResourceExposure(ResourceScope.None)]
        public static extern int DrawTextExA(HandleRef hDC, byte[] lpszString, int byteCount, ref IntNativeMethods.RECT lpRect, int nFormat, [In, Out] IntNativeMethods.DRAWTEXTPARAMS lpDTParams);
 
        public static int DrawTextEx(HandleRef hDC, string text, ref IntNativeMethods.RECT lpRect, int nFormat, [In, Out] IntNativeMethods.DRAWTEXTPARAMS lpDTParams)
        {
            int retVal;
            if( Marshal.SystemDefaultCharSize == 1)
            {
                // CapRectangleForWin9x(ref lpRect);
                // we have to do this because if we pass too big of a value (<= 2^31) to win9x
                // it fails and returns negative values as the rect in which it painted the text
                lpRect.top    = Math.Min(Int16.MaxValue, lpRect.top);
                lpRect.left   = Math.Min(Int16.MaxValue, lpRect.left);
                lpRect.right  = Math.Min(Int16.MaxValue, lpRect.right);
                lpRect.bottom = Math.Min(Int16.MaxValue, lpRect.bottom);
 
                // Convert Unicode string to ANSI.
                int byteCount = IntUnsafeNativeMethods.WideCharToMultiByte(IntNativeMethods.CP_ACP, 0, text, text.Length, null, 0, IntPtr.Zero, IntPtr.Zero);
                byte[] textBytes = new byte[byteCount];
                IntUnsafeNativeMethods.WideCharToMultiByte(IntNativeMethods.CP_ACP, 0, text, text.Length, textBytes, textBytes.Length, IntPtr.Zero, IntPtr.Zero);
            
                // Security: Windows 95/98/Me: This value may not exceed 8192.
                byteCount = Math.Min( byteCount, IntNativeMethods.MaxTextLengthInWin9x);
                retVal = DrawTextExA( hDC, textBytes, byteCount, ref lpRect, nFormat, lpDTParams );
            }
            else
            {
                retVal = DrawTextExW( hDC, text, text.Length, ref lpRect, nFormat, lpDTParams  );
            }
 
            DbgUtil.AssertWin32(retVal != 0, "DrawTextEx(hdc=[0x{0:X8}], text=[{1}], rect=[{2}], flags=[{3}] failed.", hDC.Handle, text, lpRect, nFormat );
            return retVal;
        }
 
        [SuppressMessage("Microsoft.Interoperability", "CA1400:PInvokeEntryPointsShouldExist")]            
        [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling=true, CharSet=System.Runtime.InteropServices.CharSet.Unicode)]
        [ResourceExposure(ResourceScope.None)]
        public static extern int GetTextExtentPoint32W(HandleRef hDC, string text, int len, [In, Out] IntNativeMethods.SIZE size);
        
        [SuppressMessage("Microsoft.Interoperability", "CA1400:PInvokeEntryPointsShouldExist")]            
        [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling=true, CharSet=System.Runtime.InteropServices.CharSet.Ansi)]
        [ResourceExposure(ResourceScope.None)]
        public static extern int GetTextExtentPoint32A(HandleRef hDC, byte[] lpszString, int byteCount, [In, Out] IntNativeMethods.SIZE size);
 
        public static int GetTextExtentPoint32(HandleRef hDC, string text, [In, Out] IntNativeMethods.SIZE size)
        {
            int retVal;
            int byteCount = text.Length;
 
            if( Marshal.SystemDefaultCharSize == 1)
            {
                // Convert Unicode string to ANSI.
                byteCount = IntUnsafeNativeMethods.WideCharToMultiByte(IntNativeMethods.CP_ACP, 0, text, text.Length, null, 0, IntPtr.Zero, IntPtr.Zero);
                byte[] textBytes = new byte[byteCount];
                IntUnsafeNativeMethods.WideCharToMultiByte(IntNativeMethods.CP_ACP, 0, text, text.Length, textBytes, textBytes.Length, IntPtr.Zero, IntPtr.Zero);
 
                // Security: Windows 95/98/Me: This value may not exceed 8192.
                byteCount = Math.Min( text.Length, IntNativeMethods.MaxTextLengthInWin9x);
                retVal = GetTextExtentPoint32A(hDC, textBytes, byteCount, size);
            }
            else
            {
                retVal = GetTextExtentPoint32W(hDC, text, text.Length, size);
            }
 
            DbgUtil.AssertWin32(retVal != 0, "GetTextExtentPoint32(hdc=[0x{0:X8}], text=[{1}], size=[{2}] failed.", hDC.Handle, text, size );
            return retVal;
        }
 
        // WARNING: This method is currently used just for drawing the text background (ComponentEditorForm.cs) and not for rendering text.
        //          Prefer using DrawText over this method if possible, it handles Win9x issues properly.  Ideally, we should remove this method
        //          but to avoid issues at this point I'm leaving it here.
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2101:SpecifyMarshalingForPInvokeStringArguments")]
        [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling=false, CharSet=CharSet.Auto)]
        [ResourceExposure(ResourceScope.None)]
        internal static extern bool ExtTextOut(HandleRef hdc, int x, int y, int options, ref IntNativeMethods.RECT rect, string str, int length, int[] spacing);
        
        [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling = true, EntryPoint="LineTo", CharSet = CharSet.Auto)]
        [ResourceExposure(ResourceScope.None)]
        public static extern bool IntLineTo(HandleRef hdc, int x, int y);
        public static bool LineTo(HandleRef hdc, int x, int y)
        {
            bool retVal = IntLineTo(hdc, x, y);
            DbgUtil.AssertWin32(retVal, "LineTo(hdc=[0x{0:X8}], x=[{1}], y=[{2}] failed.", hdc.Handle, x, y );
            return retVal;
        }
 
        [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling = true, EntryPoint="MoveToEx", CharSet = CharSet.Auto)]
        [ResourceExposure(ResourceScope.None)]
        public static extern bool IntMoveToEx(HandleRef hdc, int x, int y, IntNativeMethods.POINT pt);
        public static bool MoveToEx(HandleRef hdc, int x, int y, IntNativeMethods.POINT pt)
        {
            bool retVal = IntMoveToEx(hdc, x, y, pt);
            DbgUtil.AssertWin32(retVal, "MoveToEx(hdc=[0x{0:X8}], x=[{1}], y=[{2}], pt=[{3}] failed.", hdc.Handle, x, y, pt );
            return retVal;
        }
 
        [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling = true, EntryPoint="Rectangle", CharSet = CharSet.Auto)]
        [ResourceExposure(ResourceScope.None)]
        public static extern bool IntRectangle(HandleRef hdc, int left, int top, int right, int bottom);
        public static bool Rectangle(HandleRef hdc, int left, int top, int right, int bottom)
        {
            bool retVal = IntRectangle(hdc,left, top, right, bottom);
            DbgUtil.AssertWin32(retVal, "Rectangle(hdc=[0x{0:X8}], left=[{1}], top=[{2}], right=[{3}], bottom=[{4}] failed.", hdc.Handle, left, top, right, bottom );
            return retVal;
        }
 
        [DllImport(ExternDll.User32, SetLastError=true, ExactSpelling = true, EntryPoint="FillRect", CharSet = System.Runtime.InteropServices.CharSet.Auto)]
        [ResourceExposure(ResourceScope.None)]
        public static extern bool IntFillRect(HandleRef hdc, [In] ref IntNativeMethods.RECT rect, HandleRef hbrush);
        public static bool FillRect(HandleRef hDC, [In] ref IntNativeMethods.RECT rect, HandleRef hbrush)
        {
            bool retVal = IntFillRect(hDC, ref rect, hbrush);
            DbgUtil.AssertWin32(retVal, "FillRect(hdc=[0x{0:X8}], rect=[{1}], hbrush=[{2}]", hDC.Handle, rect, hbrush.Handle);
            return retVal;
        }
 
        [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling = true, EntryPoint="SetMapMode", CharSet = System.Runtime.InteropServices.CharSet.Auto)]
        [ResourceExposure(ResourceScope.None)]
        public static extern int IntSetMapMode(HandleRef hDC, int nMapMode);
        public static int SetMapMode(HandleRef hDC, int nMapMode)
        {
            int oldMapMode = IntSetMapMode(hDC, nMapMode);
            DbgUtil.AssertWin32(oldMapMode != 0, "SetMapMode(hdc=[0x{0:X8}], MapMode=[{1}]", hDC.Handle, nMapMode);
            return oldMapMode;
        }
 
        [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling=true, EntryPoint="GetMapMode", CharSet=System.Runtime.InteropServices.CharSet.Auto)]
        [ResourceExposure(ResourceScope.None)]
        public static extern int IntGetMapMode(HandleRef hDC);
        public static int GetMapMode(HandleRef hDC)
        {
            int mapMode = IntGetMapMode(hDC);
            DbgUtil.AssertWin32(mapMode != 0, "GetMapMode(hdc=[0x{0:X8}]", hDC.Handle);
            return mapMode;
        }
 
        [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling=true, EntryPoint="GetViewportExtEx")]
        [ResourceExposure(ResourceScope.None)]
        public static extern bool IntGetViewportExtEx(HandleRef hdc, [In, Out] IntNativeMethods.SIZE lpSize);
        public static bool GetViewportExtEx( HandleRef hdc, [In, Out] IntNativeMethods.SIZE lpSize )
        {
            bool retVal = IntGetViewportExtEx( hdc, lpSize );
            DbgUtil.AssertWin32(retVal, "GetViewportExtEx([hdc=0x{0:X8}], [out size]) failed.", hdc.Handle);
            return retVal;
        }
       
        [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling=true, EntryPoint="GetViewportOrgEx")]
        [ResourceExposure(ResourceScope.None)]
        public static extern bool IntGetViewportOrgEx(HandleRef hdc, [In, Out] IntNativeMethods.POINT lpPoint);
        public static bool GetViewportOrgEx( HandleRef hdc, [In, Out] IntNativeMethods.POINT lpPoint )
        {
            bool retVal = IntGetViewportOrgEx( hdc, lpPoint );
            DbgUtil.AssertWin32(retVal, "GetViewportOrgEx([hdc=0x{0:X8}], [out point]) failed.", hdc.Handle);
            return retVal;
        }
 
        [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling=true, EntryPoint="SetViewportExtEx", CharSet=System.Runtime.InteropServices.CharSet.Auto)]
        [ResourceExposure(ResourceScope.None)]
        public static extern bool IntSetViewportExtEx(HandleRef hDC, int x, int y, [In, Out] IntNativeMethods.SIZE size);
        public static bool SetViewportExtEx(HandleRef hDC, int x, int y, [In, Out] IntNativeMethods.SIZE size)
        {
            bool retVal = IntSetViewportExtEx(hDC, x, y, size);
            DbgUtil.AssertWin32(retVal, "SetViewportExtEx([hdc=0x{0:X8}], x=[{1}], y=[{2}], [out size]) failed.", hDC.Handle, x, y);
            return retVal;
        }
        [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling=true, EntryPoint="SetViewportOrgEx", CharSet=System.Runtime.InteropServices.CharSet.Auto)]
        [ResourceExposure(ResourceScope.None)]
        public static extern bool IntSetViewportOrgEx(HandleRef hDC, int x, int y, [In, Out] IntNativeMethods.POINT point);
        public static bool SetViewportOrgEx(HandleRef hDC, int x, int y, [In, Out] IntNativeMethods.POINT point)
        {
            bool retVal = IntSetViewportOrgEx(hDC, x, y, point);
            DbgUtil.AssertWin32(retVal, "SetViewportOrgEx([hdc=0x{0:X8}], x=[{1}], y=[{2}], [out point]) failed.", hDC.Handle, x, y);
            return retVal;
        }
 
        
 
        [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling=true, CharSet = System.Runtime.InteropServices.CharSet.Unicode)]
        [ResourceExposure(ResourceScope.None)]
        public static extern int GetTextMetricsW(HandleRef hDC, [In, Out] ref IntNativeMethods.TEXTMETRIC lptm);
 
        [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling=true, CharSet = System.Runtime.InteropServices.CharSet.Ansi)]
        [ResourceExposure(ResourceScope.None)]
        public static extern int GetTextMetricsA(HandleRef hDC, [In, Out] ref IntNativeMethods.TEXTMETRICA lptm);
 
        public static int GetTextMetrics(HandleRef hDC, ref IntNativeMethods.TEXTMETRIC lptm) 
        {
            int retVal;
 
            if (Marshal.SystemDefaultCharSize == 1)
            {
                // ANSI
                IntNativeMethods.TEXTMETRICA lptmA = new IntNativeMethods.TEXTMETRICA();
                retVal = IntUnsafeNativeMethods.GetTextMetricsA(hDC, ref lptmA);
 
                lptm.tmHeight           = lptmA.tmHeight; 
                lptm.tmAscent           = lptmA.tmAscent; 
                lptm.tmDescent          = lptmA.tmDescent; 
                lptm.tmInternalLeading  = lptmA.tmInternalLeading; 
                lptm.tmExternalLeading  = lptmA.tmExternalLeading; 
                lptm.tmAveCharWidth     = lptmA.tmAveCharWidth; 
                lptm.tmMaxCharWidth     = lptmA.tmMaxCharWidth; 
                lptm.tmWeight           = lptmA.tmWeight; 
                lptm.tmOverhang         = lptmA.tmOverhang; 
                lptm.tmDigitizedAspectX = lptmA.tmDigitizedAspectX; 
                lptm.tmDigitizedAspectY = lptmA.tmDigitizedAspectY; 
                lptm.tmFirstChar        = (char) lptmA.tmFirstChar; 
                lptm.tmLastChar         = (char) lptmA.tmLastChar; 
                lptm.tmDefaultChar      = (char) lptmA.tmDefaultChar; 
                lptm.tmBreakChar        = (char) lptmA.tmBreakChar; 
                lptm.tmItalic           = lptmA.tmItalic; 
                lptm.tmUnderlined       = lptmA.tmUnderlined; 
                lptm.tmStruckOut        = lptmA.tmStruckOut; 
                lptm.tmPitchAndFamily   = lptmA.tmPitchAndFamily; 
                lptm.tmCharSet          = lptmA.tmCharSet; 
            }
            else
            {
                // Unicode
                retVal = IntUnsafeNativeMethods.GetTextMetricsW(hDC, ref lptm);
            }
 
            DbgUtil.AssertWin32(retVal != 0, "GetTextMetrics(hdc=[0x{0:X8}], [out TEXTMETRIC] failed.", hDC.Handle );
            return retVal;
        }
 
        [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling=true, EntryPoint="BeginPath", CharSet=System.Runtime.InteropServices.CharSet.Auto)]
        [ResourceExposure(ResourceScope.None)]
        public static extern bool IntBeginPath(HandleRef hDC);
        public static bool BeginPath(HandleRef hDC)
        {
            bool retVal = IntBeginPath(hDC);
            DbgUtil.AssertWin32(retVal, "BeginPath(hdc=[0x{0:X8}]failed.", hDC.Handle );
            return retVal;
        }
       
        [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling=true, EntryPoint="EndPath", CharSet=System.Runtime.InteropServices.CharSet.Auto)]
        [ResourceExposure(ResourceScope.None)]
        public static extern bool IntEndPath(HandleRef hDC);
        public static bool EndPath(HandleRef hDC)
        {
            bool retVal = IntEndPath(hDC);
            DbgUtil.AssertWin32(retVal, "EndPath(hdc=[0x{0:X8}]failed.", hDC.Handle);
            return retVal;
        }
 
        [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling=true, EntryPoint="StrokePath", CharSet=System.Runtime.InteropServices.CharSet.Auto)]
        [ResourceExposure(ResourceScope.None)]
        public static extern bool IntStrokePath(HandleRef hDC);
        public static bool StrokePath(HandleRef hDC)
        {
            bool retVal = IntStrokePath(hDC);
            DbgUtil.AssertWin32(retVal, "StrokePath(hdc=[0x{0:X8}]failed.", hDC.Handle );
            return retVal;
        }
 
        [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling=true, EntryPoint="AngleArc", CharSet=System.Runtime.InteropServices.CharSet.Auto)]
        [ResourceExposure(ResourceScope.None)]
        public static extern bool IntAngleArc(HandleRef hDC, int x, int y, int radius, float startAngle, float endAngle);
        public static bool AngleArc(HandleRef hDC, int x, int y, int radius, float startAngle, float endAngle)
        {
            bool retVal = IntAngleArc(hDC, x, y, radius, startAngle, endAngle);
            DbgUtil.AssertWin32(retVal, "AngleArc(hdc=[0x{0:X8}], ...) failed.", hDC.Handle);
            return retVal;
        }
 
        [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling=true, EntryPoint="Arc", CharSet=System.Runtime.InteropServices.CharSet.Auto)]
        [ResourceExposure(ResourceScope.None)]
        public static extern bool IntArc(
            HandleRef hDC, 
            int nLeftRect,   // x-coord of rectangle's upper-left corner
            int nTopRect,    // y-coord of rectangle's upper-left corner
            int nRightRect,  // x-coord of rectangle's lower-right corner
            int nBottomRect, // y-coord of rectangle's lower-right corner
            int nXStartArc,  // x-coord of first radial ending point
            int nYStartArc,  // y-coord of first radial ending point
            int nXEndArc,    // x-coord of second radial ending point
            int nYEndArc     // y-coord of second radial ending point
            );
        public static bool Arc(
            HandleRef hDC, 
            int nLeftRect,   // x-coord of rectangle's upper-left corner
            int nTopRect,    // y-coord of rectangle's upper-left corner
            int nRightRect,  // x-coord of rectangle's lower-right corner
            int nBottomRect, // y-coord of rectangle's lower-right corner
            int nXStartArc,  // x-coord of first radial ending point
            int nYStartArc,  // y-coord of first radial ending point
            int nXEndArc,    // x-coord of second radial ending point
            int nYEndArc     // y-coord of second radial ending point
            )
        {
            bool retVal = IntArc(hDC, nLeftRect, nTopRect, nRightRect, nBottomRect, nXStartArc, nYStartArc, nXEndArc, nYEndArc);
            DbgUtil.AssertWin32(retVal, "Arc(hdc=[0x{0:X8}], ...) failed.", hDC.Handle);
            return retVal;
        }
 
        // Misc.
 
        [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling = true, CharSet = System.Runtime.InteropServices.CharSet.Auto)]
        [ResourceExposure(ResourceScope.None)]
        public static extern int SetTextAlign(HandleRef hDC, int nMode);
 
        [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling = true, EntryPoint="Ellipse", CharSet = System.Runtime.InteropServices.CharSet.Auto)]
        [ResourceExposure(ResourceScope.None)]
        public static extern bool IntEllipse(HandleRef hDc, int x1, int y1, int x2, int y2);
        public static bool Ellipse(HandleRef hDc, int x1, int y1, int x2, int y2)
        {
            bool retVal = IntEllipse(hDc, x1, y1, x2, y2);
            DbgUtil.AssertWin32(retVal, "Ellipse(hdc=[0x{0:X8}], x1=[{1}], y1=[{2}], x2=[{3}], y2=[{4}]) failed.", hDc.Handle, x1, y1, x2, y2);
            return retVal;
        }
 
        // SECREVIEW: From MSDN: Using the MultiByteToWideChar/WideCharToMultiByte function incorrectly can compromise the security of your application. 
        //            Calling the WideCharToMultiByte function can easily cause a buffer overrun because the size of the In buffer equals the number 
        //            of WCHARs in the string, while the size of the Out buffer equals the number of bytes. To avoid a buffer overrun, be sure to specify 
        //            a buffer size appropriate for the data type the buffer receives. For more information, see Security Considerations: International Features. 
        //            Always call these functions passing a null destination buffer to get its size and the create the buffer with the exact size.
        [DllImport(ExternDll.Kernel32, ExactSpelling=true, CharSet=CharSet.Unicode)]
        [ResourceExposure(ResourceScope.None)]
        public static extern int WideCharToMultiByte(int codePage, int flags, [MarshalAs(UnmanagedType.LPWStr)]string wideStr, int chars, [In, Out]byte[] pOutBytes, int bufferBytes, IntPtr defaultChar, IntPtr pDefaultUsed);
 
    }
}