Overlay indices are signed shorts (-1 means no overlay)
(ImageList_SetOverlayIndex) should accept -1 as overlayindex.
(ImageList_Read) We can read a NxM bitmap from the stream and have
to convert it into a 1x(M*N) bitmap, set cCurImage,cMaxImage. Added
documentation.
(others) removed some potential operator precendence problems.

diff --git a/dlls/comctl32/imagelist.c b/dlls/comctl32/imagelist.c
index a1c3afa..b97145c 100644
--- a/dlls/comctl32/imagelist.c
+++ b/dlls/comctl32/imagelist.c
@@ -7,7 +7,7 @@
  *    - Fix ImageList_DrawIndirect (xBitmap, yBitmap, rgbFg, rgbBk, dwRop).
  *    - Fix ImageList_GetIcon.
  *    - Fix drag functions.
- *    - Fix ImageList_Read and ImageList_Write.
+ *    - Fix ImageList_Write.
  *    - Fix ImageList_SetFilter (undocumented).
  *      BTW does anybody know anything about this function???
  *        - It removes 12 Bytes from the stack (3 Parameters).
@@ -149,6 +149,7 @@
 {
     HDC hImageDC;
     HBITMAP hOldBitmap;
+
     hImageDC = CreateCompatibleDC(0);
     hOldBitmap = SelectObject(hImageDC, pimldp->himl->hbmImage);
     BitBlt(pimldp->hdcDst, 
@@ -203,7 +204,7 @@
     /* Draw the Background for the appropriate Styles
     */
     if( bUseCustomBackground && (pimldp->fStyle == ILD_NORMAL 
-          || pimldp->fStyle & ILD_IMAGE 
+          || (pimldp->fStyle & ILD_IMAGE)
           || bBlendFlag))
     {
         hBrush = CreateSolidBrush (himlLocal->clrBk);
@@ -218,7 +219,7 @@
     /* Draw Image Transparently over the current background
     */
     if(pimldp->fStyle == ILD_NORMAL
-        || pimldp->fStyle & ILD_TRANSPARENT
+        || (pimldp->fStyle & ILD_TRANSPARENT)
         || ((pimldp->fStyle & ILD_IMAGE) && bUseCustomBackground)
         || bBlendFlag)
     {
@@ -245,7 +246,7 @@
     }
     /* Draw the image when no Background is specified
     */
-    else if(pimldp->fStyle & ILD_IMAGE && !bUseCustomBackground)
+    else if((pimldp->fStyle & ILD_IMAGE) && !bUseCustomBackground)
     {
         BitBlt(pimldp->hdcDst, 
             pimldp->x, pimldp->y, cx, cy,
@@ -1252,8 +1253,10 @@
         return FALSE;
     if (pimldp->himl == NULL)
         return FALSE;
-    if ((pimldp->i < 0) || (pimldp->i > pimldp->himl->cCurImage))
+    if ((pimldp->i < 0) || (pimldp->i > pimldp->himl->cCurImage)) {
+	ERR("%d not within range (max %d)\n",pimldp->i,pimldp->himl->cCurImage);
         return FALSE;
+    }
     /*
         Get the Height and Width to display
     */
@@ -1334,8 +1337,10 @@
 
         DeleteDC (hdcDst);
         DeleteDC (hdcSrc);
-    }
 
+	himlDst->cCurImage = himlSrc->cCurImage;
+	himlDst->cMaxImage = himlSrc->cMaxImage;
+    }
     return himlDst;
 }
 
@@ -1451,8 +1456,10 @@
     HBITMAP hOldSrcBitmap,hOldDstBitmap;
     HDC    hdcSrc, hdcDst;
 
-    if ((himl == NULL) || (i < 0) || (i >= himl->cCurImage))
+    if ((himl == NULL) || (i < 0) || (i >= himl->cCurImage)) {
+	FIXME("(%p,%d,%x), params out of range!\n",himl,i,fStyle);
 	return 0;
+   }
 
     hdcSrc = CreateCompatibleDC(0);
     hdcDst = CreateCompatibleDC(0);
@@ -1883,6 +1890,7 @@
 }
 
 
+/* helper for _read_bitmap currently unused */
 static int may_use_dibsection(HDC hdc) {
     int bitspixel = GetDeviceCaps(hdc,BITSPIXEL)*GetDeviceCaps(hdc,PLANES);
     if (bitspixel>8)
@@ -1892,7 +1900,8 @@
     return GetDeviceCaps(hdc,94) & 0x10;
 }
 
-static HBITMAP _read_bitmap(LPSTREAM pstm,int x) {
+/* helper for ImageList_Read, see comments below */
+static HBITMAP _read_bitmap(LPSTREAM pstm,int ilcFlag,int cx,int cy) {
     HDC			xdc = 0;
     BITMAPFILEHEADER	bmfh;
     BITMAPINFOHEADER	bmih;
@@ -1900,7 +1909,8 @@
     LPBITMAPINFOHEADER	bmihc = NULL;
     int			result = 0;
     HBITMAP		hbitmap = 0;
-    LPBYTE		bits = NULL;
+    LPBYTE		bits = NULL,nbits = NULL;
+    int			nbytesperline,bytesperline;
 
     if (!SUCCEEDED(IStream_Read ( pstm, &bmfh, sizeof(bmfh), NULL))	||
     	(bmfh.bfType != (('M'<<8)|'B'))					||
@@ -1922,38 +1932,62 @@
     bmihc->biSizeImage	= (longsperline*height)<<2;
 
     /* read the palette right after the end of the bitmapinfoheader */
-    if (!SUCCEEDED(IStream_Read ( pstm, bmihc+1, palspace, NULL)))
-	goto ret1;
+    if (palspace)
+	if (!SUCCEEDED(IStream_Read ( pstm, bmihc+1, palspace, NULL)))
+	    goto ret1;
 
     xdc = GetDC(0);
+#if 0 /* Magic for NxM -> 1x(N*M) not implemented for DIB Sections */
     if ((bitsperpixel>1) &&
-	((x!=0xfe) && (!x || may_use_dibsection(xdc)))
+	((ilcFlag!=ILC_COLORDDB) && (!ilcFlag || may_use_dibsection(xdc)))
      ) {
 	hbitmap = CreateDIBSection(xdc,(BITMAPINFO*)bmihc,0,(LPVOID*)&bits,0,0);
 	if (!hbitmap)
 	    goto ret1;
 	if (!SUCCEEDED(IStream_Read( pstm, bits, bmihc->biSizeImage, NULL)))
 	    goto ret1;
-	bits = NULL;
 	result = 1;
-    } else {
+    } else
+#endif
+    {
+	int i,nwidth,nheight;
+
+	nwidth	= width*(height/cy);
+	nheight	= cy;
+
 	if (bitsperpixel==1)
-	    hbitmap = CreateBitmap(width,height,1,1,NULL);
+	    hbitmap = CreateBitmap(nwidth,nheight,1,1,NULL);
 	else
-	    hbitmap = CreateCompatibleBitmap(xdc,width,height);
+	    hbitmap = CreateCompatibleBitmap(xdc,nwidth,nheight);
 
 	/* Might be a bit excessive memory use here */
-	bits = (LPBYTE)LocalAlloc(0,longsperline*4*height);
-	if (!SUCCEEDED(IStream_Read ( pstm, bits, longsperline*4*height, NULL)))
+	bits = (LPBYTE)LocalAlloc(LMEM_ZEROINIT,bmihc->biSizeImage);
+	nbits = (LPBYTE)LocalAlloc(LMEM_ZEROINIT,bmihc->biSizeImage);
+	if (!SUCCEEDED(IStream_Read ( pstm, bits, bmihc->biSizeImage, NULL)))
 		goto ret1;
-	if (!SetDIBits(xdc,hbitmap,0,height,bits,(BITMAPINFO*)bmihc,0))
+
+	/* Copy the NxM bitmap into a 1x(N*M) bitmap we need, linewise */
+	/* Do not forget that windows bitmaps are bottom->top */
+	bytesperline	= longsperline*4;
+	nbytesperline	= (height/cy)*bytesperline;
+	for (i=0;i<height;i++) {
+	    memcpy(
+		nbits+((height-i)%cy)*nbytesperline+(i/cy)*bytesperline,
+		bits+bytesperline*(height-i),
+		bytesperline
+	    );
+	}
+	bmihc->biWidth	= nwidth;
+	bmihc->biHeight	= nheight;
+	if (!SetDIBits(xdc,hbitmap,0,nheight,nbits,(BITMAPINFO*)bmihc,0))
 		goto ret1;
+	LocalFree((HLOCAL)nbits);
+	LocalFree((HLOCAL)bits);
 	result = 1;
     }
 ret1:
     if (xdc)	ReleaseDC(0,xdc);
     if (bmihc)	LocalFree((HLOCAL)bmihc);
-    if (bits)	LocalFree((HLOCAL)bits);
     if (!result) {
 	if (hbitmap) {
 	    DeleteObject(hbitmap);
@@ -1975,8 +2009,27 @@
  *     Success: handle to image list
  *     Failure: NULL
  *
- * BUGS
- *     still not complete functional
+ * The format is like this:
+ * 	ILHEAD 			ilheadstruct;
+ *
+ * for the color image part:
+ * 	BITMAPFILEHEADER	bmfh; 
+ * 	BITMAPINFOHEADER	bmih;
+ * only if it has a palette:
+ *	RGBQUAD		rgbs[nr_of_paletted_colors]; 
+ *
+ *	BYTE			colorbits[imagesize];
+ *
+ * the following only if the ILC_MASK bit is set in ILHEAD.ilFlags:
+ *	BITMAPFILEHEADER	bmfh_mask;
+ *	BITMAPINFOHEADER	bmih_mask;
+ * only if it has a palette (it usually does not):
+ *	RGBQUAD		rgbs[nr_of_paletted_colors]; 
+ *
+ *	BYTE			maskbits[imagesize];
+ *
+ * CAVEAT: Those images are within a NxM bitmap, not the 1xN we expect.
+ *         _read_bitmap needs to convert them.
  */
 HIMAGELIST WINAPI ImageList_Read (LPSTREAM pstm)
 {
@@ -1995,7 +2048,7 @@
 #if 0
     FIXME("	ilHead.cCurImage = %d\n",ilHead.cCurImage);
     FIXME("	ilHead.cMaxImage = %d\n",ilHead.cMaxImage);
-    FIXME("	ilHead.grow = %d\n",ilHead.grow);
+    FIXME("	ilHead.cGrow = %d\n",ilHead.cGrow);
     FIXME("	ilHead.cx = %d\n",ilHead.cx);
     FIXME("	ilHead.cy = %d\n",ilHead.cy);
     FIXME("	ilHead.flags = %x\n",ilHead.flags);
@@ -2005,11 +2058,11 @@
     FIXME("	ilHead.ovls[3] = %d\n",ilHead.ovls[3]);
 #endif
 
-    hbmColor = _read_bitmap(pstm,ilHead.flags & 0xfe);
+    hbmColor = _read_bitmap(pstm,ilHead.flags & ~ILC_MASK,ilHead.cx,ilHead.cy);
     if (!hbmColor)
 	return NULL;
-    if (ilHead.flags & 1) {
-	hbmMask = _read_bitmap(pstm,0);
+    if (ilHead.flags & ILC_MASK) {
+	hbmMask = _read_bitmap(pstm,0,ilHead.cx,ilHead.cy);
 	if (!hbmMask) {
 	    DeleteObject(hbmColor);
 	    return NULL;
@@ -2021,22 +2074,21 @@
 		    ilHead.cy,
 		    ilHead.flags,
 		    1,		/* initial */
-		    ilHead.grow
+		    ilHead.cGrow
     );
     if (!himl) {
 	DeleteObject(hbmColor);
 	DeleteObject(hbmMask);
 	return NULL;
-   }
-
+    }
     himl->hbmImage = hbmColor;
     himl->hbmMask = hbmMask;
+    himl->cCurImage = ilHead.cCurImage;
+    himl->cMaxImage = ilHead.cMaxImage;
 
     ImageList_SetBkColor(himl,ilHead.bkcolor);
-
     for (i=0;i<4;i++)
     	ImageList_SetOverlayImage(himl,ilHead.ovls[i],i+1);
-
     return himl;
 }
 
@@ -2593,9 +2645,8 @@
 	return FALSE;
     if ((iOverlay < 1) || (iOverlay > MAX_OVERLAYIMAGE))
 	return FALSE;
-    if ((iImage < 0) || (iImage > himl->cCurImage))
+    if ((iImage!=-1) && ((iImage < 0) || (iImage > himl->cCurImage)))
 	return FALSE;
-    
     himl->nOvlIdx[iOverlay - 1] = iImage;
     return TRUE;
 }
diff --git a/include/imagelist.h b/include/imagelist.h
index 2e2bb56..9c45222 100644
--- a/include/imagelist.h
+++ b/include/imagelist.h
@@ -48,12 +48,12 @@
     USHORT	usVersion;
     WORD	cCurImage;
     WORD	cMaxImage;
-    WORD	grow;	/* unclear */
+    WORD	cGrow;
     WORD	cx;
     WORD	cy;
     COLORREF	bkcolor;
     WORD	flags;
-    WORD	ovls[4];
+    SHORT	ovls[4];
 } ILHEAD;
 
 #include "poppack.h"