diff --git a/src/System.Windows.Forms.Primitives/src/Interop/Ole32/Interop.IFont.cs b/src/System.Windows.Forms.Primitives/src/Interop/Ole32/Interop.IFont.cs index f1a1dcf445f..5fdf0b0124c 100644 --- a/src/System.Windows.Forms.Primitives/src/Interop/Ole32/Interop.IFont.cs +++ b/src/System.Windows.Forms.Primitives/src/Interop/Ole32/Interop.IFont.cs @@ -12,7 +12,7 @@ internal static partial class Ole32 [ComImport] [Guid("BEF6E002-A874-101A-8BBA-00AA00300CAB")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] - public interface IFont + public unsafe interface IFont { string Name { get; set; } long Size { get; set; } @@ -37,6 +37,10 @@ HRESULT SetRatio( int cyLogical, int cyHimetric); + [PreserveSig] + HRESULT QueryTextMetrics( + Gdi32.TEXTMETRICW* pTM); + [PreserveSig] HRESULT AddRefHfont( IntPtr hFont); @@ -44,6 +48,10 @@ HRESULT AddRefHfont( [PreserveSig] HRESULT ReleaseHfont( IntPtr hFont); + + [PreserveSig] + HRESULT SetHdc( + IntPtr hDC); } } } diff --git a/src/System.Windows.Forms.Primitives/src/Interop/Ole32/Interop.IPicture.cs b/src/System.Windows.Forms.Primitives/src/Interop/Ole32/Interop.IPicture.cs index 28fb37651b7..0ecfd11e315 100644 --- a/src/System.Windows.Forms.Primitives/src/Interop/Ole32/Interop.IPicture.cs +++ b/src/System.Windows.Forms.Primitives/src/Interop/Ole32/Interop.IPicture.cs @@ -9,14 +9,22 @@ internal static partial class Interop { internal static partial class Ole32 { - [ComImport()] + [ComImport] [Guid("7BF80980-BF32-101A-8BBB-00AA00300CAB")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface IPicture { - uint Handle { get; } + /// + /// IPicture handles are sign extended on 64 bit devices. To preserve + /// the sign, handles should be represented as ints, not uints. + /// + int Handle { get; } - uint hPal { get; } + /// + /// HPALETTE handles are sign extended on 64 bit devices. To preserve + /// the sign, handles should be represented as ints, not uints. + /// + int hPal { get; } /// /// This is actually , but we can't describe it as such. diff --git a/src/System.Windows.Forms.Primitives/src/Interop/Ole32/Interop.IPictureDisp.cs b/src/System.Windows.Forms.Primitives/src/Interop/Ole32/Interop.IPictureDisp.cs index 1645015ef46..decab7631b8 100644 --- a/src/System.Windows.Forms.Primitives/src/Interop/Ole32/Interop.IPictureDisp.cs +++ b/src/System.Windows.Forms.Primitives/src/Interop/Ole32/Interop.IPictureDisp.cs @@ -9,14 +9,22 @@ internal static partial class Interop { internal static partial class Ole32 { - [ComImport()] + [ComImport] [Guid("7BF80981-BF32-101A-8BBB-00AA00300CAB")] [InterfaceType(ComInterfaceType.InterfaceIsIDispatch)] internal unsafe interface IPictureDisp { - uint Handle { get; } + /// + /// IPicture handles are sign extended on 64 bit devices. To preserve + /// the sign, handles should be represented as ints, not uints. + /// + int Handle { get; } - uint hPal { get; } + /// + /// HPALETTE handles are sign extended on 64 bit devices. To preserve + /// the sign, handles should be represented as ints, not uints. + /// + int hPal { get; } /// /// This is actually , but we can't describe it as such. diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/AxHost.cs b/src/System.Windows.Forms/src/System/Windows/Forms/AxHost.cs index 46f20bd325f..ba64c16d4d7 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/AxHost.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/AxHost.cs @@ -4027,7 +4027,7 @@ protected static Image GetPictureFromIPicture(object picture) return null; } - uint hPal = default; + int hPal = default; Ole32.IPicture pict = (Ole32.IPicture)picture; Ole32.PICTYPE type = (Ole32.PICTYPE)pict.Type; if (type == Ole32.PICTYPE.BITMAP) @@ -4055,7 +4055,7 @@ protected unsafe static Image GetPictureFromIPictureDisp(object picture) return null; } - uint hPal = default; + int hPal = default; Ole32.IPictureDisp pict = (Ole32.IPictureDisp)picture; Ole32.PICTYPE type = (Ole32.PICTYPE)pict.Type; if (type == Ole32.PICTYPE.BITMAP) @@ -4075,9 +4075,9 @@ protected unsafe static Image GetPictureFromIPictureDisp(object picture) } private static Image GetPictureFromParams( - uint handle, + int handle, Ole32.PICTYPE type, - uint paletteHandle, + int paletteHandle, int width, int height) { diff --git a/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/AxHostTests.cs b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/AxHostTests.cs index ec8523a5f0e..ba031ef6cd5 100644 --- a/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/AxHostTests.cs +++ b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/AxHostTests.cs @@ -999,22 +999,22 @@ public void AxHost_GetOcx_NotCreated_ReturnsNull() Assert.Null(control.GetOcx()); } - [Fact] + [WinFormsFact] public void AxHost_GetFontFromIFont_NullFont_ReturnsNull() { Assert.Null(SubAxHost.GetFontFromIFont(null)); } - [Fact] + [WinFormsFact] public void AxHost_GetFontFromIFont_InvalidFont_ThrowsInvalidCastException() { Assert.Throws(() => SubAxHost.GetFontFromIFont(new object())); } - [Fact(Skip = "Unstable test, see: https://github.com/dotnet/winforms/issues/2002")] + [WinFormsFact] public void AxHost_GetIFontDispFromFont_InvokeSimpleStyle_Roundtrips() { - Font font = new Font(SystemFonts.StatusFont.FontFamily, 10); + using var font = new Font("Arial", 10); object disp = SubAxHost.GetIFontDispFromFont(font); Ole32.IFont iFont = (Ole32.IFont)disp; Assert.Equal(font.Name, iFont.Name); @@ -1048,10 +1048,10 @@ public void AxHost_GetIFontDispFromFont_InvokeSimpleStyle_Roundtrips() Assert.Equal(1, result.GdiCharSet); } - [Fact] + [WinFormsFact] public void AxHost_GetIFontDispFromFont_InvokeComplexStyle_Roundtrips() { - Font font = new Font(SystemFonts.StatusFont.FontFamily, 10, FontStyle.Bold | FontStyle.Underline | FontStyle.Italic | FontStyle.Strikeout, GraphicsUnit.Point, 10); + using var font = new Font("Arial", 10, FontStyle.Bold | FontStyle.Underline | FontStyle.Italic | FontStyle.Strikeout, GraphicsUnit.Point, 10); object disp = SubAxHost.GetIFontDispFromFont(font); Ole32.IFont iFont = (Ole32.IFont)disp; @@ -1086,7 +1086,7 @@ public void AxHost_GetIFontDispFromFont_InvokeComplexStyle_Roundtrips() Assert.Equal(10, result.GdiCharSet); } - [Theory] + [WinFormsTheory] [InlineData(GraphicsUnit.Document)] [InlineData(GraphicsUnit.Inch)] [InlineData(GraphicsUnit.Millimeter)] @@ -1094,20 +1094,20 @@ public void AxHost_GetIFontDispFromFont_InvokeComplexStyle_Roundtrips() [InlineData(GraphicsUnit.World)] public void AxHost_GetIFontDispFromFont_InvalidFontUnit_ThrowsArgumentException(GraphicsUnit unit) { - var font = new Font(SystemFonts.StatusFont.FontFamily, 10, unit); + using var font = new Font("Arial", 10, unit); Assert.Throws("font", () => SubAxHost.GetIFontDispFromFont(font)); } - [Fact] + [WinFormsFact] public void AxHost_GetIFontDispFromFont_NullFont_ReturnsNull() { Assert.Null(SubAxHost.GetIFontDispFromFont(null)); } - [Fact(Skip = "Unstable test, see: https://github.com/dotnet/winforms/issues/2003")] + [WinFormsFact] public void AxHost_GetIFontFromFont_InvokeSimpleStyle_Roundtrips() { - Font font = new Font(SystemFonts.StatusFont.FontFamily, 10); + using var font = new Font("Arial", 10); Ole32.IFont iFont = (Ole32.IFont)SubAxHost.GetIFontFromFont(font); Assert.Equal(font.Name, iFont.Name); Assert.Equal(97500, iFont.Size); @@ -1125,10 +1125,10 @@ public void AxHost_GetIFontFromFont_InvokeSimpleStyle_Roundtrips() Assert.Equal(1, result.GdiCharSet); } - [Fact] + [WinFormsFact] public void AxHost_GetIFontFromFont_InvokeComplexStyle_Roundtrips() { - Font font = new Font(SystemFonts.StatusFont.FontFamily, 10, FontStyle.Bold | FontStyle.Underline | FontStyle.Italic | FontStyle.Strikeout, GraphicsUnit.Point, 10); + using var font = new Font("Arial", 10, FontStyle.Bold | FontStyle.Underline | FontStyle.Italic | FontStyle.Strikeout, GraphicsUnit.Point, 10); Ole32.IFont iFont = (Ole32.IFont)SubAxHost.GetIFontFromFont(font); Assert.Equal(font.Name, iFont.Name); Assert.Equal(97500, iFont.Size); @@ -1146,7 +1146,7 @@ public void AxHost_GetIFontFromFont_InvokeComplexStyle_Roundtrips() Assert.Equal(10, result.GdiCharSet); } - [Theory] + [WinFormsTheory] [InlineData(GraphicsUnit.Document)] [InlineData(GraphicsUnit.Inch)] [InlineData(GraphicsUnit.Millimeter)] @@ -1154,23 +1154,23 @@ public void AxHost_GetIFontFromFont_InvokeComplexStyle_Roundtrips() [InlineData(GraphicsUnit.World)] public void AxHost_GetIFontFromFont_InvalidFontUnit_ThrowsArgumentException(GraphicsUnit unit) { - var font = new Font(SystemFonts.StatusFont.FontFamily, 10, unit); + using var font = new Font("Arial", 10, unit); Assert.Throws("font", () => SubAxHost.GetIFontFromFont(font)); } - [Fact] + [WinFormsFact] public void AxHost_GetIFontFromFont_NullFont_ReturnsNull() { Assert.Null(SubAxHost.GetIFontFromFont(null)); } - [Fact] + [WinFormsFact] public void AxHost_GetIPictureFromCursor_Invoke_Roundtrips() { var original = new Cursor("bitmaps/cursor.cur"); IPicture iPicture = (IPicture)SubAxHost.GetIPictureFromCursor(original); Assert.NotNull(iPicture); - Assert.NotEqual(0u, iPicture.Handle); + Assert.NotEqual(0, iPicture.Handle); Assert.Throws(() => iPicture.hPal); Assert.Equal(3, iPicture.Type); Assert.Equal(847, iPicture.Width); @@ -1181,7 +1181,7 @@ public void AxHost_GetIPictureFromCursor_Invoke_Roundtrips() Assert.Throws(() => SubAxHost.GetPictureFromIPicture(iPicture)); } - [Fact] + [WinFormsFact] public void AxHost_GetIPictureDispFromPicture_InvokeBitmap_Roundtrips() { var original = new Bitmap(10, 11); @@ -1189,18 +1189,18 @@ public void AxHost_GetIPictureDispFromPicture_InvokeBitmap_Roundtrips() object disp = SubAxHost.GetIPictureDispFromPicture(original); IPicture iPicture = (IPicture)disp; Assert.NotNull(iPicture); - Assert.NotEqual(0u, iPicture.Handle); - Assert.Equal(0u, iPicture.hPal); + Assert.NotEqual(0, iPicture.Handle); + Assert.Equal(0, iPicture.hPal); Assert.Equal(1, iPicture.Type); Assert.Equal(265, iPicture.Width); Assert.Equal(291, iPicture.Height); - Assert.Equal(0u, iPicture.CurDC); + Assert.Equal(0, iPicture.CurDC); Assert.Equal(0u, iPicture.Attributes); Ole32.IPictureDisp iPictureDisp = (Ole32.IPictureDisp)disp; Assert.NotNull(iPictureDisp); - Assert.NotEqual(0u, iPictureDisp.Handle); - Assert.Equal(0u, iPictureDisp.hPal); + Assert.NotEqual(0, iPictureDisp.Handle); + Assert.Equal(0, iPictureDisp.hPal); Assert.Equal(1, iPictureDisp.Type); Assert.Equal(265, iPictureDisp.Width); Assert.Equal(291, iPictureDisp.Height); @@ -1216,7 +1216,7 @@ public void AxHost_GetIPictureDispFromPicture_InvokeBitmap_Roundtrips() Assert.Equal(Color.FromArgb(unchecked((int)0xFF010203)), original.GetPixel(1, 2)); } - [Fact(Skip = "Unstable test, see: https://github.com/dotnet/winforms/issues/2005")] + [WinFormsFact] public void AxHost_GetIPictureDispFromPicture_InvokeEnhancedMetafile_Roundtrips() { var original = new Metafile("bitmaps/milkmateya01.emf"); @@ -1224,7 +1224,7 @@ public void AxHost_GetIPictureDispFromPicture_InvokeEnhancedMetafile_Roundtrips( IPicture iPicture = (IPicture)disp; Assert.NotNull(iPicture); - Assert.NotEqual(0u, iPicture.Handle); + Assert.NotEqual(0, iPicture.Handle); Assert.Throws(() => iPicture.hPal); Assert.Equal(4, iPicture.Type); Assert.Equal(19972, iPicture.Width); @@ -1234,7 +1234,7 @@ public void AxHost_GetIPictureDispFromPicture_InvokeEnhancedMetafile_Roundtrips( Ole32.IPictureDisp iPictureDisp = (Ole32.IPictureDisp)disp; Assert.NotNull(iPictureDisp); - Assert.NotEqual(0u, iPictureDisp.Handle); + Assert.NotEqual(0, iPictureDisp.Handle); TargetInvocationException ex = Assert.Throws(() => iPictureDisp.hPal); Assert.IsType(ex.InnerException); Assert.Equal(4, iPictureDisp.Type); @@ -1248,32 +1248,32 @@ public void AxHost_GetIPictureDispFromPicture_InvokeEnhancedMetafile_Roundtrips( Assert.Equal(new Size(759, 1073), result.Size); } - [Fact] + [WinFormsFact] public void AxHost_GetIPictureDispFromPicture_InvokeMetafile_ThrowsCOMException() { var original = new Metafile("bitmaps/telescope_01.wmf"); Assert.Throws(() => SubAxHost.GetIPictureDispFromPicture(original)); } - [Fact] + [WinFormsFact] public void AxHost_GetIPictureDispFromPicture_NullImage_ReturnsNull() { Assert.Null(SubAxHost.GetIPictureDispFromPicture(null)); } - [Fact] + [WinFormsFact] public void AxHost_GetIPictureFromPicture_InvokeBitmap_Roundtrips() { var original = new Bitmap(10, 11); original.SetPixel(1, 2, Color.FromArgb(unchecked((int)0xFF010203))); IPicture iPicture = (IPicture)SubAxHost.GetIPictureFromPicture(original); Assert.NotNull(iPicture); - Assert.NotEqual(0u, iPicture.Handle); - Assert.Equal(0u, iPicture.hPal); + Assert.NotEqual(0, iPicture.Handle); + Assert.Equal(0, iPicture.hPal); Assert.Equal(1, iPicture.Type); Assert.Equal(265, iPicture.Width); Assert.Equal(291, iPicture.Height); - Assert.Equal(0u, iPicture.CurDC); + Assert.Equal(0, iPicture.CurDC); Assert.Equal(0u, iPicture.Attributes); var result = Assert.IsType(SubAxHost.GetPictureFromIPicture(iPicture)); @@ -1282,13 +1282,13 @@ public void AxHost_GetIPictureFromPicture_InvokeBitmap_Roundtrips() Assert.Equal(Color.FromArgb(unchecked((int)0xFF010203)), original.GetPixel(1, 2)); } - [Fact(Skip = "Unstable test, see: https://github.com/dotnet/winforms/issues/2004")] + [WinFormsFact] public void AxHost_GetIPictureFromPicture_InvokeEnhancedMetafile_Roundtrips() { var original = new Metafile("bitmaps/milkmateya01.emf"); IPicture iPicture = (IPicture)SubAxHost.GetIPictureFromPicture(original); Assert.NotNull(iPicture); - Assert.NotEqual(0u, iPicture.Handle); + Assert.NotEqual(0, iPicture.Handle); Assert.Throws(() => iPicture.hPal); Assert.Equal(4, iPicture.Type); Assert.Equal(19972, iPicture.Width); @@ -1300,26 +1300,26 @@ public void AxHost_GetIPictureFromPicture_InvokeEnhancedMetafile_Roundtrips() Assert.Equal(new Size(759, 1073), result.Size); } - [Fact] + [WinFormsFact] public void AxHost_GetIPictureFromPicture_InvokeMetafile_ThrowsCOMException() { var original = new Metafile("bitmaps/telescope_01.wmf"); Assert.Throws(() => SubAxHost.GetIPictureFromPicture(original)); } - [Fact] + [WinFormsFact] public void AxHost_GetIPictureFromPicture_NullImage_ReturnsNull() { Assert.Null(SubAxHost.GetIPictureFromPicture(null)); } - [Fact] + [WinFormsFact] public void AxHost_GetPictureFromIPicture_InvokeInvalid_ThrowsInvalidCastException() { Assert.Throws(() => SubAxHost.GetPictureFromIPicture(new object())); } - [Fact] + [WinFormsFact] public void AxHost_GetPictureFromIPicture_NullPicture_ReturnsNull() { Assert.Null(SubAxHost.GetPictureFromIPicture(null)); @@ -1414,11 +1414,11 @@ public SubAxHost(string clsid, int flags) : base(clsid, flags) [ComImport] [Guid("7BF80980-BF32-101A-8BBB-00AA00300CAB")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] - private interface IPicture + private unsafe interface IPicture { - uint Handle { get; } + int Handle { get; } - uint hPal { get; } + int hPal { get; } short Type { get; } @@ -1426,7 +1426,8 @@ private interface IPicture int Height { get; } - void Render( + [PreserveSig] + HRESULT Render( IntPtr hDC, int x, int y, @@ -1436,23 +1437,28 @@ void Render( long ySrc, long cxSrc, long cySrc, - ref RECT pRcWBounds); + RECT* pRcWBounds); - void SetHPal(uint hPal); + void SetHPal(int hPal); - uint CurDC { get; } + int CurDC { get; } - uint SelectPicture( - IntPtr hDC, - out IntPtr phDCOut); + [PreserveSig] + HRESULT SelectPicture( + IntPtr hDCIn, + IntPtr* phDCOut, + int* phBmpOut); BOOL KeepOriginalFormat { get; set; } - void PictureChanged(); + [PreserveSig] + HRESULT PictureChanged(); - int SaveAsFile( + [PreserveSig] + HRESULT SaveAsFile( IntPtr pStream, - BOOL fSaveMemCopy); + BOOL fSaveMemCopy, + int* pCbSize); uint Attributes { get; } } diff --git a/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/ComponentModel/Com2Interop/COM2PictureConverterTests.cs b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/ComponentModel/Com2Interop/COM2PictureConverterTests.cs index 53bd2986656..17f1c2ef8a0 100644 --- a/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/ComponentModel/Com2Interop/COM2PictureConverterTests.cs +++ b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/ComponentModel/Com2Interop/COM2PictureConverterTests.cs @@ -6,6 +6,7 @@ using System.Windows.Forms.ComponentModel.Com2Interop; using Moq; using Xunit; +using static Interop; using static Interop.Ole32; namespace System.Windows.Forms.Tests.ComponentModel.Com2Interop @@ -31,7 +32,7 @@ public void ConvertNativeToManaged_Null() public void ConvertNativeToManaged_NullHandle() { var mock = new Mock(MockBehavior.Strict); - mock.Setup(m => m.Handle).Returns(0u); + mock.Setup(m => m.Handle).Returns(0); Assert.Null(Instance.ConvertNativeToManaged(mock.Object, null)); } @@ -41,7 +42,7 @@ public void ConvertNativeToManaged_Icon() Icon errorIcon = SystemIcons.Error; var mock = new Mock(MockBehavior.Strict); - mock.Setup(m => m.Handle).Returns((uint)errorIcon.Handle); + mock.Setup(m => m.Handle).Returns((int)errorIcon.Handle); mock.Setup(m => m.Type).Returns((short)PICTYPE.ICON); using Icon icon = (Icon)Instance.ConvertNativeToManaged(mock.Object, null); @@ -59,26 +60,33 @@ public void ConvertNativeToManaged_Bitmap() { Icon errorIcon = SystemIcons.Error; using Bitmap errorBitmap = errorIcon.ToBitmap(); + IntPtr hBitmap = errorBitmap.GetHbitmap(); + try + { + var mock = new Mock(MockBehavior.Strict); + mock.Setup(m => m.Handle).Returns((int)hBitmap); + mock.Setup(m => m.Type).Returns((short)PICTYPE.BITMAP); - var mock = new Mock(MockBehavior.Strict); - mock.Setup(m => m.Handle).Returns((uint)errorBitmap.GetHbitmap()); - mock.Setup(m => m.Type).Returns((short)PICTYPE.BITMAP); - - using Bitmap bitmap = (Bitmap)Instance.ConvertNativeToManaged(mock.Object, null); + using Bitmap bitmap = (Bitmap)Instance.ConvertNativeToManaged(mock.Object, null); - Assert.Equal(bitmap.Height, errorIcon.Height); - Assert.Equal(bitmap.Width, errorIcon.Width); - Assert.Equal(typeof(Bitmap), Instance.ManagedType); + Assert.Equal(bitmap.Height, errorIcon.Height); + Assert.Equal(bitmap.Width, errorIcon.Width); + Assert.Equal(typeof(Bitmap), Instance.ManagedType); - // We should get the cached object if the handle didn't change - Assert.Same(bitmap, (Bitmap)Instance.ConvertNativeToManaged(mock.Object, null)); + // We should get the cached object if the handle didn't change + Assert.Same(bitmap, (Bitmap)Instance.ConvertNativeToManaged(mock.Object, null)); + } + finally + { + Gdi32.DeleteObject(hBitmap); + } } [Fact] public void ConvertNativeToManaged_UnsupportedPICTYPE() { var mock = new Mock(MockBehavior.Strict); - mock.Setup(m => m.Handle).Returns(1u); + mock.Setup(m => m.Handle).Returns(1); mock.Setup(m => m.Type).Returns((short)PICTYPE.METAFILE); // The converter asserts, but doesn't throw. Suppress asserts so