From 116c0cd9a57e579ed620725463580cdac1fc25c6 Mon Sep 17 00:00:00 2001 From: Doug Lyons Date: Sat, 27 Apr 2024 14:38:06 -0500 Subject: [PATCH] [USER32] Fix resource display of MSVC BI_BITFIELD 32-bit bitmaps. (#5942) This specifically fixes Wordpad's Open and SaveAs dialog toolbars. * Fix 16 bpp BI_BITFIELDS like 32 bpp was done. * Add BI_BITFIELDS byte count into bitmap_info_size return value. * Account for GCC's windres.exe incorrect omission for BI_BITFIELDS DWORD's when processing 32-bpp bitmaps. * Account for GCC's windres.exe failing with bitmaps with BI_BITFIELDS and bits per plane is 16 * Fix WARN message to show error on either 16-bpp or 32-bpp * Correct comment regarding GCC compiled bitmaps with compression of BI_BITFIELD's to add 16 bits per plane CORE-17005 --- win32ss/user/user32/windows/cursoricon.c | 33 +++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/win32ss/user/user32/windows/cursoricon.c b/win32ss/user/user32/windows/cursoricon.c index eb160a88c13..531c29abe57 100644 --- a/win32ss/user/user32/windows/cursoricon.c +++ b/win32ss/user/user32/windows/cursoricon.c @@ -152,6 +152,8 @@ static BOOL is_dib_monochrome( const BITMAPINFO* info ) } } +/* Return the size of the bitmap info structure including color table and + * the bytes required for 3 DWORDS if this is a BI_BITFIELDS bmp. */ static int bitmap_info_size( const BITMAPINFO * info, WORD coloruse ) { unsigned int colors, size, masks = 0; @@ -170,8 +172,21 @@ static int bitmap_info_size( const BITMAPINFO * info, WORD coloruse ) colors = 256; if (!colors && (info->bmiHeader.biBitCount <= 8)) colors = 1 << info->bmiHeader.biBitCount; + /* Account for BI_BITFIELDS in BITMAPINFOHEADER(v1-v3) bmp's. The + * 'max' selection using biSize below will exclude v4 & v5's. */ if (info->bmiHeader.biCompression == BI_BITFIELDS) masks = 3; size = max( info->bmiHeader.biSize, sizeof(BITMAPINFOHEADER) + masks * sizeof(DWORD) ); + /* Test for BI_BITFIELDS format and either 16 or 32 bpp. + * If so, account for the 3 DWORD masks (RGB Order). + * BITMAPCOREHEADER tested above has no 16 or 32 bpp types. + * See table "All of the possible pixel formats in a DIB" + * at https://en.wikipedia.org/wiki/BMP_file_format. */ + if (info->bmiHeader.biSize >= sizeof(BITMAPV4HEADER) && + info->bmiHeader.biCompression == BI_BITFIELDS && + (info->bmiHeader.biBitCount == 16 || info->bmiHeader.biBitCount == 32)) + { + size += 3 * sizeof(DWORD); // BI_BITFIELDS + } return size + colors * ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD)); } } @@ -1099,7 +1114,7 @@ BITMAP_LoadImageW( HBITMAP hbmpOld, hbmpRet = NULL; LONG width, height; WORD bpp; - DWORD compr; + DWORD compr, ResSize = 0; /* Map the bitmap info */ if(fuLoad & LR_LOADFROMFILE) @@ -1137,6 +1152,7 @@ BITMAP_LoadImageW( pbmi = LockResource(hgRsrc); if(!pbmi) return NULL; + ResSize = SizeofResource(hinst, hrsrc); } /* Fix up values */ @@ -1162,6 +1178,21 @@ BITMAP_LoadImageW( goto end; CopyMemory(pbmiCopy, pbmi, iBMISize); + TRACE("Size Image %d, Size Header %d, ResSize %d\n", + pbmiCopy->bmiHeader.biSizeImage, pbmiCopy->bmiHeader.biSize, ResSize); + + /* HACK: If this is a binutils' windres.exe compiled 16 or 32 bpp bitmap + * using BI_BITFIELDS, then a bug causes it to fail to include + * the bytes for the bitfields. So, we have to substract out the + * size of the bitfields previously included from bitmap_info_size. */ + if (compr == BI_BITFIELDS && (bpp == 16 || bpp == 32) && + pbmiCopy->bmiHeader.biSizeImage + pbmiCopy->bmiHeader.biSize == ResSize) + { + /* GCC pointer to the image data has 12 less bytes than MSVC */ + pvBits = (char*)pvBits - 12; + WARN("Found GCC Resource Compiled 16-bpp or 32-bpp error\n"); + } + /* Fix it up, if needed */ if(fuLoad & (LR_LOADTRANSPARENT | LR_LOADMAP3DCOLORS)) {