Skip to content

Commit

Permalink
Remove AOT warnings for S.Drawing.Common (#61567)
Browse files Browse the repository at this point in the history
* Remove AOT warnings for S.Drawing.Common
- `Marshal.SizeOf(Type)` replaced with `Marshal.SizeOt<T>()`
- `Marshal.PtrToStructure(IntrPtr, Type)` replaced with `Marshal.PtrToStructure<T>(IntPtr)`

* Use pointers where possible

* Ref return PRINTDLG

* Use GeneratedDllImport

Co-authored-by: Jan Kotas <jkotas@microsoft.com>
  • Loading branch information
kant2002 and jkotas committed Dec 14, 2021
1 parent 2658a0b commit 6b224f3
Show file tree
Hide file tree
Showing 17 changed files with 155 additions and 203 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,14 @@ internal static partial class Interop
{
internal static partial class Comdlg32
{
#pragma warning disable DLLIMPORTGENANALYZER015 // Use 'GeneratedDllImportAttribute' instead of 'DllImportAttribute' to generate P/Invoke marshalling code at compile time
// TODO: [DllImportGenerator] Switch to use GeneratedDllImport once we support non-blittable structs.
[DllImport(Libraries.Comdlg32, CharSet = CharSet.Auto, SetLastError = true)]
internal static extern bool PrintDlg([In, Out] PRINTDLG lppd);
[GeneratedDllImport(Libraries.Comdlg32, CharSet = CharSet.Auto, SetLastError = true)]
internal static partial bool PrintDlg(ref PRINTDLG lppd);

[DllImport(Libraries.Comdlg32, CharSet = CharSet.Auto, SetLastError = true)]
internal static extern bool PrintDlg([In, Out] PRINTDLGX86 lppd);
#pragma warning restore DLLIMPORTGENANALYZER015
[GeneratedDllImport(Libraries.Comdlg32, CharSet = CharSet.Auto, SetLastError = true)]
internal static partial bool PrintDlg(ref PRINTDLGX86 lppd);

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
internal sealed class PRINTDLG
[StructLayout(LayoutKind.Sequential)]
internal struct PRINTDLG
{
internal int lStructSize;
internal IntPtr hwndOwner;
Expand All @@ -35,14 +32,14 @@ internal sealed class PRINTDLG
internal IntPtr lCustData;
internal IntPtr lpfnPrintHook;
internal IntPtr lpfnSetupHook;
internal string? lpPrintTemplateName;
internal string? lpSetupTemplateName;
internal IntPtr lpPrintTemplateName;
internal IntPtr lpSetupTemplateName;
internal IntPtr hPrintTemplate;
internal IntPtr hSetupTemplate;
}

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto, Pack = 1)]
internal sealed class PRINTDLGX86
[StructLayout(LayoutKind.Sequential, Pack = 1)]
internal struct PRINTDLGX86
{
internal int lStructSize;
internal IntPtr hwndOwner;
Expand All @@ -59,8 +56,8 @@ internal sealed class PRINTDLGX86
internal IntPtr lCustData;
internal IntPtr lpfnPrintHook;
internal IntPtr lpfnSetupHook;
internal string? lpPrintTemplateName;
internal string? lpSetupTemplateName;
internal IntPtr lpPrintTemplateName;
internal IntPtr lpSetupTemplateName;
internal IntPtr hPrintTemplate;
internal IntPtr hSetupTemplate;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ Unix support is disabled by default. See https://aka.ms/systemdrawingnonwindows
<Compile Include="System\Drawing\Imaging\ColorMatrix.cs" />
<Compile Include="System\Drawing\Imaging\ColorPalette.cs" />
<Compile Include="System\Drawing\Imaging\EncoderParameter.cs" />
<Compile Include="System\Drawing\Imaging\EncoderParameterPrivate.cs" />
<Compile Include="System\Drawing\Imaging\EncoderParameters.cs" />
<Compile Include="System\Drawing\Imaging\ImageAttributes.cs" />
<Compile Include="System\Drawing\Imaging\ImageCodecInfo.cs" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -367,14 +367,14 @@ public const int
public const int ERROR_CANCELLED = 1223;

[StructLayout(LayoutKind.Sequential)]
public class ENHMETAHEADER
public struct ENHMETAHEADER
{
/// The ENHMETAHEADER structure is defined natively as a union with WmfHeader.
/// Extreme care should be taken if changing the layout of the corresponding managed
/// structures to minimize the risk of buffer overruns. The affected managed classes
/// are the following: ENHMETAHEADER, MetaHeader, MetafileHeaderWmf, MetafileHeaderEmf.
public int iType;
public int nSize = 40; // ndirect.DllLib.sizeOf( this )
public int nSize;
// rclBounds was a by-value RECTL structure
public int rclBounds_left;
public int rclBounds_top;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ private void CopyFromScreenX11(int sourceX, int sourceY, int destinationX, int d
/* Get XVisualInfo for this visual */
visual.visualid = LibX11Functions.XVisualIDFromVisual(defvisual);
vPtr = LibX11Functions.XGetVisualInfo(Gdip.Display, 0x1 /* VisualIDMask */, ref visual, ref nitems);
visual = (XVisualInfo)Marshal.PtrToStructure(vPtr, typeof(XVisualInfo))!;
visual = Marshal.PtrToStructure<XVisualInfo>(vPtr)!;
image = LibX11Functions.XGetImage(Gdip.Display, window, sourceX, sourceY, blockRegionSize.Width,
blockRegionSize.Height, AllPlanes, 2 /* ZPixmap*/);
if (image == IntPtr.Zero)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,6 @@ namespace System.Drawing.Imaging
[StructLayout(LayoutKind.Sequential)]
public sealed unsafe class EncoderParameter : IDisposable
{
#pragma warning disable CS0618 // Legacy code: We don't care about using obsolete API's.
[MarshalAs(UnmanagedType.Struct)]
#pragma warning restore CS0618
private Guid _parameterGuid; // GUID of the parameter
private readonly int _numberOfValues; // Number of the parameter values
private readonly EncoderParameterValueType _parameterValueType; // Value type, like ValueTypeLONG etc.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Runtime.InteropServices;

namespace System.Drawing.Imaging
{
[StructLayout(LayoutKind.Sequential)]
internal struct EncoderParameterPrivate
{
public Guid ParameterGuid; // GUID of the parameter
public int NumberOfValues; // Number of the parameter values
public EncoderParameterValueType ParameterValueType; // Value type, like ValueTypeLONG etc.
public IntPtr ParameterValue; // A pointer to the parameter values
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,9 @@ public EncoderParameter[] Param
/// Also, in 64-bit platforms, 'Count' is aligned in 8 bytes (4 extra padding bytes) so we use IntPtr instead of Int32 to account for
/// that.
/// </summary>
internal IntPtr ConvertToMemory()
internal unsafe IntPtr ConvertToMemory()
{
int size = Marshal.SizeOf(typeof(EncoderParameter));
int size = sizeof(EncoderParameterPrivate);

int length = _param.Length;
IntPtr memory = Marshal.AllocHGlobal(checked(length * size + IntPtr.Size));
Expand All @@ -74,27 +74,21 @@ internal IntPtr ConvertToMemory()
/// Copy the native GDI+ EncoderParameters data from a chunk of memory into a managed EncoderParameters object.
/// See ConvertToMemory for more info.
/// </summary>
internal static EncoderParameters ConvertFromMemory(IntPtr memory)
internal static unsafe EncoderParameters ConvertFromMemory(IntPtr memory)
{
if (memory == IntPtr.Zero)
{
throw Gdip.StatusException(Gdip.InvalidParameter);
}

int count = Marshal.ReadInt32(memory);

int count = *(int*)memory;
EncoderParameterPrivate* parameters = (EncoderParameterPrivate*)((byte*)memory + IntPtr.Size);
EncoderParameters p = new EncoderParameters(count);
int size = Marshal.SizeOf(typeof(EncoderParameter));
long arrayOffset = (long)memory + IntPtr.Size;

for (int i = 0; i < count; i++)
{
Guid guid = (Guid)Marshal.PtrToStructure((IntPtr)(i * size + arrayOffset), typeof(Guid))!;
int numberOfValues = Marshal.ReadInt32((IntPtr)(i * size + arrayOffset + 16));
EncoderParameterValueType type = (EncoderParameterValueType)Marshal.ReadInt32((IntPtr)(i * size + arrayOffset + 20));
IntPtr value = Marshal.ReadIntPtr((IntPtr)(i * size + arrayOffset + 24));
ref readonly EncoderParameterPrivate param = ref parameters[i];

p._param[i] = new EncoderParameter(new Encoder(guid), numberOfValues, type, value);
p._param[i] = new EncoderParameter(new Encoder(param.ParameterGuid), param.NumberOfValues, param.ParameterValueType, param.ParameterValue);
}

return p;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -169,41 +169,38 @@ public static ImageCodecInfo[] GetImageEncoders()
return imageCodecs;
}

private static ImageCodecInfo[] ConvertFromMemory(IntPtr memoryStart, int numCodecs)
private static unsafe ImageCodecInfo[] ConvertFromMemory(IntPtr memoryStart, int numCodecs)
{
ImageCodecInfo[] codecs = new ImageCodecInfo[numCodecs];

int index;

for (index = 0; index < numCodecs; index++)
{
IntPtr curcodec = (IntPtr)((long)memoryStart + (int)Marshal.SizeOf(typeof(ImageCodecInfoPrivate)) * index);
ImageCodecInfoPrivate codecp = new ImageCodecInfoPrivate();
Marshal.PtrToStructure(curcodec, codecp);
ref readonly ImageCodecInfoPrivate codecp = ref ((ImageCodecInfoPrivate*)memoryStart)[index];

codecs[index] = new ImageCodecInfo();
codecs[index].Clsid = codecp.Clsid;
codecs[index].FormatID = codecp.FormatID;
codecs[index].CodecName = Marshal.PtrToStringUni(codecp.CodecName);
codecs[index].DllName = Marshal.PtrToStringUni(codecp.DllName);
codecs[index].FormatDescription = Marshal.PtrToStringUni(codecp.FormatDescription);
codecs[index].FilenameExtension = Marshal.PtrToStringUni(codecp.FilenameExtension);
codecs[index].MimeType = Marshal.PtrToStringUni(codecp.MimeType);
var codec = new ImageCodecInfo();
codec.Clsid = codecp.Clsid;
codec.FormatID = codecp.FormatID;
codec.CodecName = Marshal.PtrToStringUni(codecp.CodecName);
codec.DllName = Marshal.PtrToStringUni(codecp.DllName);
codec.FormatDescription = Marshal.PtrToStringUni(codecp.FormatDescription);
codec.FilenameExtension = Marshal.PtrToStringUni(codecp.FilenameExtension);
codec.MimeType = Marshal.PtrToStringUni(codecp.MimeType);

codecs[index].Flags = (ImageCodecFlags)codecp.Flags;
codecs[index].Version = (int)codecp.Version;
codec.Flags = (ImageCodecFlags)codecp.Flags;
codec.Version = (int)codecp.Version;

codecs[index].SignaturePatterns = new byte[codecp.SigCount][];
codecs[index].SignatureMasks = new byte[codecp.SigCount][];
codec.SignaturePatterns = new byte[codecp.SigCount][];
codec.SignatureMasks = new byte[codecp.SigCount][];

for (int j = 0; j < codecp.SigCount; j++)
{
codecs[index].SignaturePatterns![j] = new byte[codecp.SigSize];
codecs[index].SignatureMasks![j] = new byte[codecp.SigSize];

Marshal.Copy((IntPtr)((long)codecp.SigMask + j * codecp.SigSize), codecs[index].SignatureMasks![j], 0, codecp.SigSize);
Marshal.Copy((IntPtr)((long)codecp.SigPattern + j * codecp.SigSize), codecs[index].SignaturePatterns![j], 0, codecp.SigSize);
codec.SignaturePatterns[j] = new ReadOnlySpan<byte>((byte*)codecp.SigPattern + j * codecp.SigSize, codecp.SigSize).ToArray();
codec.SignatureMasks[j] = new ReadOnlySpan<byte>((byte*)codecp.SigMask + j * codecp.SigSize, codecp.SigSize).ToArray();
}

codecs[index] = codec;
}

return codecs;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,29 +7,24 @@ namespace System.Drawing.Imaging

// sdkinc\imaging.h
[StructLayout(LayoutKind.Sequential, Pack = 8)]
internal sealed class ImageCodecInfoPrivate
internal struct ImageCodecInfoPrivate
{
#pragma warning disable CS0618 // Legacy code: We don't care about using obsolete API's.
[MarshalAs(UnmanagedType.Struct)]
#pragma warning restore CS0618
public Guid Clsid;
#pragma warning disable CS0618 // Legacy code: We don't care about using obsolete API's.
[MarshalAs(UnmanagedType.Struct)]
#pragma warning restore CS0618

public Guid FormatID;

public IntPtr CodecName = IntPtr.Zero;
public IntPtr DllName = IntPtr.Zero;
public IntPtr FormatDescription = IntPtr.Zero;
public IntPtr FilenameExtension = IntPtr.Zero;
public IntPtr MimeType = IntPtr.Zero;
public IntPtr CodecName;
public IntPtr DllName;
public IntPtr FormatDescription;
public IntPtr FilenameExtension;
public IntPtr MimeType;

public int Flags;
public int Version;
public int SigCount;
public int SigSize;

public IntPtr SigPattern = IntPtr.Zero;
public IntPtr SigMask = IntPtr.Zero;
public IntPtr SigPattern;
public IntPtr SigMask;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ public IntPtr GetHenhmetafile()

public MetafileHeader GetMetafileHeader()
{
IntPtr header = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(MetafileHeader)));
IntPtr header = Marshal.AllocHGlobal(Marshal.SizeOf<MetafileHeader>());
try
{
int status = Gdip.GdipGetMetafileHeaderFromMetafile(nativeImage, header);
Expand All @@ -270,7 +270,7 @@ public MetafileHeader GetMetafileHeader()

public static MetafileHeader GetMetafileHeader(IntPtr henhmetafile)
{
IntPtr header = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(MetafileHeader)));
IntPtr header = Marshal.AllocHGlobal(Marshal.SizeOf<MetafileHeader>());
try
{
int status = Gdip.GdipGetMetafileHeaderFromEmf(henhmetafile, header);
Expand All @@ -288,7 +288,7 @@ public static MetafileHeader GetMetafileHeader(Stream stream)
if (stream == null)
throw new NullReferenceException(nameof(stream));

IntPtr header = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(MetafileHeader)));
IntPtr header = Marshal.AllocHGlobal(Marshal.SizeOf<MetafileHeader>());
try
{
// With libgdiplus we use a custom API for this, because there's no easy way
Expand All @@ -315,7 +315,7 @@ public static MetafileHeader GetMetafileHeader(string fileName)
// Called in order to emulate exception behavior from .NET Framework related to invalid file paths.
Path.GetFullPath(fileName);

IntPtr header = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(MetafileHeader)));
IntPtr header = Marshal.AllocHGlobal(Marshal.SizeOf<MetafileHeader>());
try
{
int status = Gdip.GdipGetMetafileHeaderFromFile(fileName, header);
Expand All @@ -330,7 +330,7 @@ public static MetafileHeader GetMetafileHeader(string fileName)

public static MetafileHeader GetMetafileHeader(IntPtr hmetafile, WmfPlaceableFileHeader wmfHeader)
{
IntPtr header = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(MetafileHeader)));
IntPtr header = Marshal.AllocHGlobal(Marshal.SizeOf<MetafileHeader>());
try
{
int status = Gdip.GdipGetMetafileHeaderFromEmf(hmetafile, header);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ public static MetafileHeader GetMetafileHeader(string fileName)

MetafileHeader header = new MetafileHeader();

IntPtr memory = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(MetafileHeaderEmf)));
IntPtr memory = Marshal.AllocHGlobal(Marshal.SizeOf<MetafileHeaderEmf>());

try
{
Expand All @@ -273,14 +273,14 @@ public static MetafileHeader GetMetafileHeader(string fileName)
metafileType == MetafileType.WmfPlaceable)
{
// WMF header
header.wmf = (MetafileHeaderWmf)Marshal.PtrToStructure(memory, typeof(MetafileHeaderWmf))!;
header.wmf = Marshal.PtrToStructure<MetafileHeaderWmf>(memory)!;
header.emf = null;
}
else
{
// EMF header
header.wmf = null;
header.emf = (MetafileHeaderEmf)Marshal.PtrToStructure(memory, typeof(MetafileHeaderEmf))!;
header.emf = Marshal.PtrToStructure<MetafileHeaderEmf>(memory)!;
}
}
finally
Expand All @@ -298,7 +298,7 @@ public static MetafileHeader GetMetafileHeader(Stream stream)
{
MetafileHeader header;

IntPtr memory = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(MetafileHeaderEmf)));
IntPtr memory = Marshal.AllocHGlobal(Marshal.SizeOf<MetafileHeaderEmf>());

try
{
Expand All @@ -317,14 +317,14 @@ public static MetafileHeader GetMetafileHeader(Stream stream)
metafileType == MetafileType.WmfPlaceable)
{
// WMF header
header.wmf = (MetafileHeaderWmf)Marshal.PtrToStructure(memory, typeof(MetafileHeaderWmf))!;
header.wmf = Marshal.PtrToStructure<MetafileHeaderWmf>(memory)!;
header.emf = null;
}
else
{
// EMF header
header.wmf = null;
header.emf = (MetafileHeaderEmf)Marshal.PtrToStructure(memory, typeof(MetafileHeaderEmf))!;
header.emf = Marshal.PtrToStructure<MetafileHeaderEmf>(memory)!;
}
}
finally
Expand All @@ -342,7 +342,7 @@ public MetafileHeader GetMetafileHeader()
{
MetafileHeader header;

IntPtr memory = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(MetafileHeaderEmf)));
IntPtr memory = Marshal.AllocHGlobal(Marshal.SizeOf<MetafileHeaderEmf>());

try
{
Expand All @@ -360,14 +360,14 @@ public MetafileHeader GetMetafileHeader()
metafileType == MetafileType.WmfPlaceable)
{
// WMF header
header.wmf = (MetafileHeaderWmf)Marshal.PtrToStructure(memory, typeof(MetafileHeaderWmf))!;
header.wmf = Marshal.PtrToStructure<MetafileHeaderWmf>(memory)!;
header.emf = null;
}
else
{
// EMF header
header.wmf = null;
header.emf = (MetafileHeaderEmf)Marshal.PtrToStructure(memory, typeof(MetafileHeaderEmf))!;
header.emf = Marshal.PtrToStructure<MetafileHeaderEmf>(memory)!;
}
}
finally
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ public sealed class MetafileHeader

internal MetafileHeader(IntPtr henhmetafile)
{
Marshal.PtrToStructure(henhmetafile, this);
Marshal.PtrToStructure<MetafileHeader>(henhmetafile, this);
}

// methods
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ internal sealed class MetafileHeaderWmf
/// structures to minimize the risk of buffer overruns. The affected managed classes
/// are the following: ENHMETAHEADER, MetaHeader, MetafileHeaderWmf, MetafileHeaderEmf.
public MetafileType type = MetafileType.Invalid;
public int size = Marshal.SizeOf(typeof(MetafileHeaderWmf));
public int size = Marshal.SizeOf<MetafileHeaderWmf>();
public int version;
public EmfPlusFlags emfPlusFlags;
public float dpiX;
Expand Down
Loading

0 comments on commit 6b224f3

Please sign in to comment.