[PATCH] comctl32/imagelist: fix ImageList_Read/Write.

Denis Malikov mdn40000 at mail.ru
Sat Jun 16 11:19:54 CDT 2018


From: Denis Malikov <mdn40000 at mail.ru>
Date: Sat, 16 Jun 2018 16:35:45 +0700
Subject: [PATCH] comctl32/imagelist: fix ImageList_Read/Write.

Fix for versions x600 and x620 and pointer calculation for mixing image and mask bits.

Tested on ReactOS 0.4.10 with *.reg files extracted from:
 - XP/2003 key HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\TrayNotify;
 - Vista/7 key HKEY_CLASSES_ROOT\Local Settings\Software\Microsoft\Windows\CurrentVersion\TrayNotify

Signed-off-by: Denis Malikov <mdn40000 at mail.ru>
---
 dlls/comctl32/imagelist.c | 59 +++++++++++++++++++++++++++--------------------
 1 file changed, 34 insertions(+), 25 deletions(-)

diff --git a/dlls/comctl32/imagelist.c b/dlls/comctl32/imagelist.c
index a08d60752e..052d59f9e4 100644
--- a/dlls/comctl32/imagelist.c
+++ b/dlls/comctl32/imagelist.c
@@ -59,7 +59,7 @@ struct _IMAGELIST
     INT         cGrow;                     /* 0C: cGrow */
     INT         cx;                        /* 10: cx */
     INT         cy;                        /* 14: cy */
-    DWORD       x4;
+    DWORD       x4;                        /* hack for IL from stream. Keep version here */
     UINT        flags;                     /* 1C: flags */
     COLORREF    clrFg;                     /* 20: foreground color */
     COLORREF    clrBk;                     /* 24: background color */
@@ -83,6 +83,7 @@ struct _IMAGELIST
 };
 
 #define IMAGELIST_MAGIC 0x53414D58
+#define IMAGELIST_VERSION 0x101
 
 /* Header used by ImageList_Read() and ImageList_Write() */
 #include "pshpack2.h"
@@ -806,6 +807,7 @@ ImageList_Create (INT cx, INT cy, UINT flags,
     himl->clrFg     = CLR_DEFAULT;
     himl->clrBk     = CLR_NONE;
     himl->color_table_set = FALSE;
+    himl->x4        = 0;
 
     /* initialize overlay mask indices */
     for (nCount = 0; nCount < MAX_OVERLAYIMAGE; nCount++)
@@ -2257,38 +2259,43 @@ HIMAGELIST WINAPI ImageList_Read(IStream *pstm)
     BITMAPINFO *image_info = (BITMAPINFO *)image_buf;
     BITMAPINFO *mask_info = (BITMAPINFO *)mask_buf;
     void *image_bits, *mask_bits = NULL;
-    ILHEAD	ilHead;
-    HIMAGELIST	himl;
+    ILHEAD ilHead;
+    HIMAGELIST himl;
     unsigned int i;
 
     TRACE("%p\n", pstm);
 
     if (FAILED(IStream_Read (pstm, &ilHead, sizeof(ILHEAD), NULL)))
-	return NULL;
+        return NULL;
     if (ilHead.usMagic != (('L' << 8) | 'I'))
-	return NULL;
-    if (ilHead.usVersion != 0x101) /* probably version? */
-	return NULL;
+        return NULL;
+    if (ilHead.usVersion != IMAGELIST_VERSION && 
+        ilHead.usVersion != 0x600 && /* XP/2003 version */
+        ilHead.usVersion != 0x620)   /* Vista/7 version */
+        return NULL;
 
     TRACE("cx %u, cy %u, flags 0x%04x, cCurImage %u, cMaxImage %u\n",
           ilHead.cx, ilHead.cy, ilHead.flags, ilHead.cCurImage, ilHead.cMaxImage);
 
     himl = ImageList_Create(ilHead.cx, ilHead.cy, ilHead.flags, ilHead.cCurImage, ilHead.cMaxImage);
     if (!himl)
-	return NULL;
+        return NULL;
+
+    // keep version from stream
+    himl->x4 = ilHead.usVersion;
 
     if (!(image_bits = read_bitmap(pstm, image_info)))
     {
-	WARN("failed to read bitmap from stream\n");
-	return NULL;
+        WARN("failed to read bitmap from stream\n");
+        return NULL;
     }
     if (ilHead.flags & ILC_MASK)
     {
         if (!(mask_bits = read_bitmap(pstm, mask_info)))
         {
             WARN("failed to read mask bitmap from stream\n");
-	    return NULL;
-	}
+            return NULL;
+        }
     }
     else mask_info = NULL;
 
@@ -2296,23 +2303,25 @@ HIMAGELIST WINAPI ImageList_Read(IStream *pstm)
     {
         DWORD *ptr = image_bits;
         BYTE *mask_ptr = mask_bits;
-        int stride = himl->cy * image_info->bmiHeader.biWidth;
+        int stride = himl->cy * (ilHead.usVersion != IMAGELIST_VERSION ? himl->cx : image_info->bmiHeader.biWidth);
+        int image_step = ilHead.usVersion != IMAGELIST_VERSION ? 1 : TILE_COUNT;
+        int mask_step = ilHead.usVersion != IMAGELIST_VERSION ? 4 : 8;
 
         if (image_info->bmiHeader.biHeight > 0)  /* bottom-up */
         {
             ptr += image_info->bmiHeader.biHeight * image_info->bmiHeader.biWidth - stride;
-            mask_ptr += (image_info->bmiHeader.biHeight * image_info->bmiHeader.biWidth - stride) / 8;
+            mask_ptr += (image_info->bmiHeader.biHeight * image_info->bmiHeader.biWidth - stride) / mask_step;
             stride = -stride;
             image_info->bmiHeader.biHeight = himl->cy;
         }
         else image_info->bmiHeader.biHeight = -himl->cy;
 
-        for (i = 0; i < ilHead.cCurImage; i += TILE_COUNT)
+        for (i = 0; i < ilHead.cCurImage; i += image_step)
         {
-            add_dib_bits( himl, i, min( ilHead.cCurImage - i, TILE_COUNT ),
+            add_dib_bits( himl, i, min( ilHead.cCurImage - i, image_step ),
                           himl->cx, himl->cy, image_info, mask_info, ptr, mask_ptr );
             ptr += stride;
-            mask_ptr += stride / 8;
+            mask_ptr += stride / mask_step;
         }
     }
     else
@@ -2333,7 +2342,7 @@ HIMAGELIST WINAPI ImageList_Read(IStream *pstm)
 
     ImageList_SetBkColor(himl,ilHead.bkcolor);
     for (i=0;i<4;i++)
-	ImageList_SetOverlayImage(himl,ilHead.ovls[i],i+1);
+        ImageList_SetOverlayImage(himl,ilHead.ovls[i],i+1);
     return himl;
 }
 
@@ -3078,10 +3087,10 @@ BOOL WINAPI ImageList_Write(HIMAGELIST himl, IStream *pstm)
     TRACE("%p %p\n", himl, pstm);
 
     if (!is_valid(himl))
-	return FALSE;
+        return FALSE;
 
     ilHead.usMagic   = (('L' << 8) | 'I');
-    ilHead.usVersion = 0x101;
+    ilHead.usVersion = himl->x4 > 0 ? himl->x4 : IMAGELIST_VERSION;
     ilHead.cCurImage = himl->cCurImage;
     ilHead.cMaxImage = himl->cMaxImage;
     ilHead.cGrow     = himl->cGrow;
@@ -3090,23 +3099,23 @@ BOOL WINAPI ImageList_Write(HIMAGELIST himl, IStream *pstm)
     ilHead.bkcolor   = himl->clrBk;
     ilHead.flags     = himl->flags;
     for(i = 0; i < 4; i++) {
-	ilHead.ovls[i] = himl->nOvlIdx[i];
+        ilHead.ovls[i] = himl->nOvlIdx[i];
     }
 
     TRACE("cx %u, cy %u, flags 0x04%x, cCurImage %u, cMaxImage %u\n",
           ilHead.cx, ilHead.cy, ilHead.flags, ilHead.cCurImage, ilHead.cMaxImage);
 
     if(FAILED(IStream_Write(pstm, &ilHead, sizeof(ILHEAD), NULL)))
-	return FALSE;
+        return FALSE;
 
     /* write the bitmap */
     if(!_write_bitmap(himl->hbmImage, pstm))
-	return FALSE;
+        return FALSE;
 
     /* write the mask if we have one */
     if(himl->flags & ILC_MASK) {
-	if(!_write_bitmap(himl->hbmMask, pstm))
-	    return FALSE;
+        if(!_write_bitmap(himl->hbmMask, pstm))
+            return FALSE;
     }
 
     return TRUE;
-- 
2.16.2.windows.1



More information about the wine-devel mailing list