using System; using System.Diagnostics.CodeAnalysis; using System.Runtime.InteropServices; using HandyControl.Tools.Interop; namespace HandyControl.Data; internal sealed class ImageCodecInfo { private string _dllName; public Guid Clsid { get; set; } public Guid FormatID { get; set; } public string CodecName { get; set; } public string DllName { [SuppressMessage("Microsoft.Security", "CA2103:ReviewImperativeSecurity")] get { if (_dllName != null) { new System.Security.Permissions.FileIOPermission(System.Security.Permissions.FileIOPermissionAccess.PathDiscovery, _dllName).Demand(); } return _dllName; } [SuppressMessage("Microsoft.Security", "CA2103:ReviewImperativeSecurity")] set { if (value != null) { new System.Security.Permissions.FileIOPermission(System.Security.Permissions.FileIOPermissionAccess.PathDiscovery, value).Demand(); } _dllName = value; } } public string FormatDescription { get; set; } public string FilenameExtension { get; set; } public string MimeType { get; set; } public ImageCodecFlags Flags { get; set; } public int Version { get; set; } public byte[][] SignaturePatterns { get; set; } public byte[][] SignatureMasks { get; set; } public static ImageCodecInfo[] GetImageDecoders() { ImageCodecInfo[] imageCodecs; var status = InteropMethods.Gdip.GdipGetImageDecodersSize(out var numDecoders, out var size); if (status != InteropMethods.Gdip.Ok) { throw InteropMethods.Gdip.StatusException(status); } var memory = Marshal.AllocHGlobal(size); try { status = InteropMethods.Gdip.GdipGetImageDecoders(numDecoders, size, memory); if (status != InteropMethods.Gdip.Ok) { throw InteropMethods.Gdip.StatusException(status); } imageCodecs = ConvertFromMemory(memory, numDecoders); } finally { Marshal.FreeHGlobal(memory); } return imageCodecs; } public static ImageCodecInfo[] GetImageEncoders() { ImageCodecInfo[] imageCodecs; var status = InteropMethods.Gdip.GdipGetImageEncodersSize(out var numEncoders, out var size); if (status != InteropMethods.Gdip.Ok) { throw InteropMethods.Gdip.StatusException(status); } var memory = Marshal.AllocHGlobal(size); try { status = InteropMethods.Gdip.GdipGetImageEncoders(numEncoders, size, memory); if (status != InteropMethods.Gdip.Ok) { throw InteropMethods.Gdip.StatusException(status); } imageCodecs = ConvertFromMemory(memory, numEncoders); } finally { Marshal.FreeHGlobal(memory); } return imageCodecs; } public static ImageCodecInfo[] ConvertFromMemory(IntPtr memoryStart, int numCodecs) { var codecs = new ImageCodecInfo[numCodecs]; int index; for (index = 0; index < numCodecs; index++) { var curcodec = (IntPtr) ((long) memoryStart + Marshal.SizeOf(typeof(InteropValues.ImageCodecInfoPrivate)) * index); var codecp = new InteropValues.ImageCodecInfoPrivate(); InteropMethods.PtrToStructure(curcodec, codecp); codecs[index] = new ImageCodecInfo { Clsid = codecp.Clsid, FormatID = codecp.FormatID, CodecName = Marshal.PtrToStringUni(codecp.CodecName), DllName = Marshal.PtrToStringUni(codecp.DllName), FormatDescription = Marshal.PtrToStringUni(codecp.FormatDescription), FilenameExtension = Marshal.PtrToStringUni(codecp.FilenameExtension), MimeType = Marshal.PtrToStringUni(codecp.MimeType), Flags = (ImageCodecFlags) codecp.Flags, Version = codecp.Version, SignaturePatterns = new byte[codecp.SigCount][], SignatureMasks = new byte[codecp.SigCount][] }; for (var 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); } } return codecs; } }