/ src / modules / MouseWithoutBorders / App / Class / MyKnownBitmap.cs
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  }