MyKnownBitmap.cs
1 // Copyright (c) Microsoft Corporation 2 // The Microsoft Corporation licenses this file to you under the MIT license. 3 // See the LICENSE file in the project root for more information. 4 5 // <summary> 6 // Customed bitmap parser. 7 // </summary> 8 // <history> 9 // 2008 created by Truong Do (ductdo). 10 // 2009-... modified by Truong Do (TruongDo). 11 // 2023- Included in PowerToys. 12 // </history> 13 using System; 14 using System.Diagnostics.CodeAnalysis; 15 using System.Drawing; 16 using System.Drawing.Imaging; 17 using System.Globalization; 18 using System.IO; 19 using System.Runtime.InteropServices; 20 21 [module: SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Scope = "member", Target = "MouseWithoutBorders.MyKnownBitmap.#FromFile(System.string)", Justification = "Dotnet port with style preservation")] 22 23 namespace MouseWithoutBorders.Class 24 { 25 #if CUSTOMIZE_LOGON_SCREEN 26 internal class MyKnownBitmap 27 { 28 private const int BITMAP_FILE_HEADER_SIZE = 14; 29 30 [StructLayout(LayoutKind.Sequential, Pack = 1, Size = BITMAP_FILE_HEADER_SIZE)] 31 private struct BITMAPFILEHEADER 32 { 33 public ushort BfType; 34 public uint BfSize; 35 public ushort BfReserved1; 36 public ushort BfReserved2; 37 public uint BfOffBits; 38 } 39 40 private const int BITMAP_INFO_HEADER_SIZE = 40; 41 42 [StructLayout(LayoutKind.Sequential, Pack = 1)] 43 private struct BITMAPINFOHEADER 44 { 45 public uint BiSize; 46 public int BiWidth; 47 public int BiHeight; 48 public ushort BiPlanes; 49 public ushort BiBitCount; 50 public uint BiCompression; 51 public uint BiSizeImage; 52 public int BiXPelsPerMeter; 53 public int BiYPelsPerMeter; 54 public uint BiClrUsed; 55 public uint BiClrImportant; 56 } 57 58 private const long MAX_FILE_SIZE = 10 * 1024 * 1024; 59 60 internal static object FromFile(string bitmapFile) 61 { 62 IntPtr p; 63 byte[] buf; 64 65 try 66 { 67 FileStream f = File.OpenRead(bitmapFile); 68 long fs = f.Length; 69 70 if (fs is < 1024 or > MAX_FILE_SIZE) 71 { 72 f.Close(); 73 return string.Format(CultureInfo.CurrentCulture, "File Size exception: {0}", fs); 74 } 75 76 BITMAPFILEHEADER bitmapFileHeader; 77 buf = new byte[BITMAP_FILE_HEADER_SIZE]; 78 p = Marshal.AllocHGlobal(BITMAP_FILE_HEADER_SIZE); 79 80 if (buf == null) 81 { 82 f.Close(); 83 return "p or buf is null! (1)"; 84 } 85 86 _ = f.Read(buf, 0, buf.Length); 87 Marshal.Copy(buf, 0, p, buf.Length); 88 bitmapFileHeader = (BITMAPFILEHEADER)Marshal.PtrToStructure(p, typeof(BITMAPFILEHEADER)); 89 Marshal.FreeHGlobal(p); 90 91 BITMAPINFOHEADER bitmapInfoHeader; 92 buf = new byte[BITMAP_INFO_HEADER_SIZE]; 93 p = Marshal.AllocHGlobal(BITMAP_INFO_HEADER_SIZE); 94 95 if (buf == null) 96 { 97 f.Close(); 98 return "p or buf is null! (2)"; 99 } 100 101 _ = f.Read(buf, 0, buf.Length); 102 Marshal.Copy(buf, 0, p, buf.Length); 103 bitmapInfoHeader = (BITMAPINFOHEADER)Marshal.PtrToStructure(p, typeof(BITMAPINFOHEADER)); 104 Marshal.FreeHGlobal(p); 105 106 if (bitmapFileHeader.BfType != 0x4D42 || bitmapFileHeader.BfSize != fs || bitmapFileHeader.BfOffBits != BITMAP_FILE_HEADER_SIZE + BITMAP_INFO_HEADER_SIZE || 107 bitmapInfoHeader.BiBitCount != 24 || bitmapInfoHeader.BiCompression != 0 || bitmapInfoHeader.BiSize != BITMAP_INFO_HEADER_SIZE || bitmapInfoHeader.BiPlanes != 1 || 108 bitmapInfoHeader.BiWidth <= 0 || bitmapInfoHeader.BiWidth > 4096 || 109 bitmapInfoHeader.BiHeight <= 0 || bitmapInfoHeader.BiHeight > 4096) 110 { 111 f.Close(); 112 return string.Format( 113 CultureInfo.CurrentCulture, 114 "Bitmap Format Exception: {0} {1} {2} {3} {4} {5} {6} {7} {8} {9} {10}", 115 bitmapFileHeader.BfType, 116 bitmapFileHeader.BfSize, 117 bitmapFileHeader.BfOffBits, 118 bitmapInfoHeader.BiBitCount, 119 bitmapInfoHeader.BiCompression, 120 bitmapInfoHeader.BiSize, 121 bitmapInfoHeader.BiPlanes, 122 bitmapInfoHeader.BiWidth, 123 bitmapInfoHeader.BiWidth, 124 bitmapInfoHeader.BiHeight, 125 bitmapInfoHeader.BiHeight); 126 } 127 128 Bitmap bm = new(bitmapInfoHeader.BiWidth, bitmapInfoHeader.BiHeight, PixelFormat.Format24bppRgb); 129 BitmapData bd = bm.LockBits(new Rectangle(0, 0, bm.Width, bm.Height), ImageLockMode.WriteOnly, PixelFormat.Format24bppRgb); 130 buf = new byte[bm.Width * bm.Height * 3]; 131 _ = f.Read(buf, 0, buf.Length); 132 f.Close(); 133 int ws = buf.Length < (bd.Width * bd.Stride) ? buf.Length : bd.Width * bd.Stride; 134 135 // Should never happen 136 if (ws <= 0) 137 { 138 bm.UnlockBits(bd); 139 bm.Dispose(); 140 return string.Format(CultureInfo.CurrentCulture, "Something wrong: {0} {1} {2}", buf.Length, bd.Width, bd.Stride); 141 } 142 143 Marshal.Copy(buf, 0, bd.Scan0, ws); 144 bm.UnlockBits(bd); 145 bm.RotateFlip(RotateFlipType.Rotate180FlipX); 146 return bm; 147 } 148 catch (Exception e) 149 { 150 return e.Message + e.StackTrace; 151 } 152 } 153 154 private MyKnownBitmap() 155 { 156 } 157 } 158 #endif 159 }