Check for failed allocations. Spotted by Martin Bealby.
[reactos.git] / reactos / lib / user32 / windows / icon.c
index 807aa6d..28d36ad 100644 (file)
@@ -16,7 +16,7 @@
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
-/* $Id: icon.c,v 1.16 2003/12/09 20:58:16 weiden Exp $
+/* $Id$
  *
  * PROJECT:         ReactOS user32.dll
  * FILE:            lib/user32/windows/icon.c
 
 /* INCLUDES ******************************************************************/
 
-#include <windows.h>
 #include <user32.h>
-#include <string.h>
-#include <stdlib.h>
+#define NDEBUG
 #include <debug.h>
 
+
 /* FUNCTIONS *****************************************************************/
 
 HICON
 ICON_CreateIconFromData(HDC hDC, PVOID ImageData, ICONIMAGE* IconImage, int cxDesired, int cyDesired, int xHotspot, int yHotspot)
 {
-  BITMAPINFO* bwBIH;
-  ICONINFO IconInfo;
-
-  IconInfo.fIcon = TRUE;
-  IconInfo.xHotspot = xHotspot;
-  IconInfo.yHotspot = yHotspot;
-  
-  /* Load the XOR bitmap */
-  IconInfo.hbmColor = CreateDIBitmap(hDC, &IconImage->icHeader, CBM_INIT,
-                                    ImageData, (BITMAPINFO*)IconImage, DIB_RGB_COLORS);
-
-  /* make ImageData point to the start of the AND image data */
-  ImageData = ((PBYTE)ImageData) + (((IconImage->icHeader.biWidth * 
-                                      IconImage->icHeader.biBitCount + 31) & ~31) >> 3) * 
+   BYTE BitmapInfoBuffer[sizeof(BITMAPINFOHEADER) + 2 * sizeof(RGBQUAD)];
+   BITMAPINFO *bwBIH = (BITMAPINFO *)BitmapInfoBuffer;
+   ICONINFO IconInfo;
+
+   IconInfo.fIcon = TRUE;
+   IconInfo.xHotspot = xHotspot;
+   IconInfo.yHotspot = yHotspot;
+
+   /* Load the XOR bitmap */
+   IconInfo.hbmColor = CreateDIBitmap(hDC, &IconImage->icHeader, CBM_INIT,
+                                      ImageData, (BITMAPINFO*)IconImage,
+                                      DIB_RGB_COLORS);
+
+   /* Make ImageData point to the start of the AND image data. */
+   ImageData = ((PBYTE)ImageData) + (((IconImage->icHeader.biWidth *
+                                      IconImage->icHeader.biBitCount + 31) & ~31) >> 3) *
                                       (IconImage->icHeader.biHeight );
 
-  /* create a BITMAPINFO header for the monocrome part of the icon */
-  bwBIH = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof (BITMAPINFOHEADER)+2*sizeof(RGBQUAD));
-
-  bwBIH->bmiHeader.biBitCount = 1;
-  bwBIH->bmiHeader.biWidth = IconImage->icHeader.biWidth;
-  bwBIH->bmiHeader.biHeight = IconImage->icHeader.biHeight;
-  bwBIH->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
-  bwBIH->bmiHeader.biPlanes = 1;
-  bwBIH->bmiHeader.biSizeImage = (((IconImage->icHeader.biWidth * 1 + 31) & ~31) >> 3) * 
-                                    (IconImage->icHeader.biHeight );
-  bwBIH->bmiHeader.biCompression = BI_RGB;
-  bwBIH->bmiHeader.biClrImportant = 0;
-  bwBIH->bmiHeader.biClrUsed = 0;
-  bwBIH->bmiHeader.biXPelsPerMeter = 0;
-  bwBIH->bmiHeader.biYPelsPerMeter = 0;
-
-  bwBIH->bmiColors[0].rgbBlue = 0;
-  bwBIH->bmiColors[0].rgbGreen = 0;
-  bwBIH->bmiColors[0].rgbRed = 0;
-  bwBIH->bmiColors[0].rgbReserved = 0;
-
-  bwBIH->bmiColors[1].rgbBlue = 0xff;
-  bwBIH->bmiColors[1].rgbGreen = 0xff;
-  bwBIH->bmiColors[1].rgbRed = 0xff;
-  bwBIH->bmiColors[1].rgbReserved = 0;
-
-  /* load the AND bitmap */
-  IconInfo.hbmMask = CreateDIBitmap(hDC, &bwBIH->bmiHeader, 0,
-                                    ImageData, bwBIH, DIB_RGB_COLORS);
-  
-  SetDIBits(hDC, IconInfo.hbmMask, 0, IconImage->icHeader.biHeight, 
-            ImageData, bwBIH, DIB_RGB_COLORS);
-  
-  RtlFreeHeap(RtlGetProcessHeap(), 0, bwBIH);
-  
-  /* Create the icon based on everything we have so far */
-  return NtUserCreateCursorIconHandle(&IconInfo, FALSE);
+   /* Create a BITMAPINFO header for the monocrome part of the icon. */
+   bwBIH->bmiHeader.biBitCount = 1;
+   bwBIH->bmiHeader.biWidth = IconImage->icHeader.biWidth;
+   bwBIH->bmiHeader.biHeight = IconImage->icHeader.biHeight;
+   bwBIH->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+   bwBIH->bmiHeader.biPlanes = 1;
+   bwBIH->bmiHeader.biSizeImage = 0;
+   bwBIH->bmiHeader.biCompression = BI_RGB;
+   bwBIH->bmiHeader.biClrImportant = 0;
+   bwBIH->bmiHeader.biClrUsed = 0;
+   bwBIH->bmiHeader.biXPelsPerMeter = 0;
+   bwBIH->bmiHeader.biYPelsPerMeter = 0;
+
+   bwBIH->bmiColors[0].rgbBlue = 0;
+   bwBIH->bmiColors[0].rgbGreen = 0;
+   bwBIH->bmiColors[0].rgbRed = 0;
+   bwBIH->bmiColors[0].rgbReserved = 0;
+
+   bwBIH->bmiColors[1].rgbBlue = 0xff;
+   bwBIH->bmiColors[1].rgbGreen = 0xff;
+   bwBIH->bmiColors[1].rgbRed = 0xff;
+   bwBIH->bmiColors[1].rgbReserved = 0;
+
+   /* Load the AND bitmap. */
+   IconInfo.hbmMask = CreateDIBitmap(hDC, &bwBIH->bmiHeader, 0,
+                                     ImageData, bwBIH, DIB_RGB_COLORS);
+
+   SetDIBits(hDC, IconInfo.hbmMask, 0, IconImage->icHeader.biHeight,
+             ImageData, bwBIH, DIB_RGB_COLORS);
+
+   /* Create the icon based on everything we have so far */
+   return NtUserCreateCursorIconHandle(&IconInfo, FALSE);
 }
 
 HICON
 ICON_CreateCursorFromData(HDC hDC, PVOID ImageData, ICONIMAGE* IconImage, int cxDesired, int cyDesired, int xHotspot, int yHotspot)
 {
-  /* FIXME - color cursors */
-  BITMAPINFO* bwBIH;
-  ICONINFO IconInfo;
-  PVOID XORImageData = ImageData;
-
-  IconInfo.fIcon = TRUE;
-  IconInfo.xHotspot = xHotspot;
-  IconInfo.yHotspot = yHotspot;
-  
-  /* create a BITMAPINFO header for the monocrome part of the icon */
-  bwBIH = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof (BITMAPINFOHEADER)+2*sizeof(RGBQUAD));
-
-  bwBIH->bmiHeader.biBitCount = 1;
-  bwBIH->bmiHeader.biWidth = IconImage->icHeader.biWidth;
-  bwBIH->bmiHeader.biHeight = IconImage->icHeader.biHeight;
-  bwBIH->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
-  bwBIH->bmiHeader.biPlanes = 1;
-  bwBIH->bmiHeader.biSizeImage = (((IconImage->icHeader.biWidth * 1 + 31) & ~31) >> 3) * 
-                                    (IconImage->icHeader.biHeight );
-  bwBIH->bmiHeader.biCompression = BI_RGB;
-  bwBIH->bmiHeader.biClrImportant = 0;
-  bwBIH->bmiHeader.biClrUsed = 0;
-  bwBIH->bmiHeader.biXPelsPerMeter = 0;
-  bwBIH->bmiHeader.biYPelsPerMeter = 0;
-
-  bwBIH->bmiColors[0].rgbBlue = 0;
-  bwBIH->bmiColors[0].rgbGreen = 0;
-  bwBIH->bmiColors[0].rgbRed = 0;
-  bwBIH->bmiColors[0].rgbReserved = 0;
-
-  bwBIH->bmiColors[1].rgbBlue = 0xff;
-  bwBIH->bmiColors[1].rgbGreen = 0xff;
-  bwBIH->bmiColors[1].rgbRed = 0xff;
-  bwBIH->bmiColors[1].rgbReserved = 0;
-
-  /* load the AND bitmap */
-  IconInfo.hbmMask = CreateDIBitmap(hDC, &bwBIH->bmiHeader, 0,
-                                    XORImageData, bwBIH, DIB_RGB_COLORS);
-  
-  if(IconInfo.hbmMask)
-  {
-    SetDIBits(hDC, IconInfo.hbmMask, 0, IconImage->icHeader.biHeight, 
-              XORImageData, bwBIH, DIB_RGB_COLORS);
-
-  }
-  
-  IconInfo.hbmColor = (HBITMAP)0;
-  
-  RtlFreeHeap(RtlGetProcessHeap(), 0, bwBIH);
-  
-  /* Create the icon based on everything we have so far */
-  return NtUserCreateCursorIconHandle(&IconInfo, FALSE);
+   /* FIXME - color cursors */
+   BYTE BitmapInfoBuffer[sizeof(BITMAPINFOHEADER) + 2 * sizeof(RGBQUAD)];
+   BITMAPINFO *bwBIH = (BITMAPINFO *)BitmapInfoBuffer;
+   ICONINFO IconInfo;
+   PVOID XORImageData = ImageData;
+
+   IconInfo.fIcon = FALSE;
+   IconInfo.xHotspot = xHotspot;
+   IconInfo.yHotspot = yHotspot;
+
+   /* Create a BITMAPINFO header for the monocrome part of the icon */
+   bwBIH->bmiHeader.biBitCount = 1;
+   bwBIH->bmiHeader.biWidth = IconImage->icHeader.biWidth;
+   bwBIH->bmiHeader.biHeight = IconImage->icHeader.biHeight;
+   bwBIH->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+   bwBIH->bmiHeader.biPlanes = 1;
+   bwBIH->bmiHeader.biSizeImage = 0;
+   bwBIH->bmiHeader.biCompression = BI_RGB;
+   bwBIH->bmiHeader.biClrImportant = 0;
+   bwBIH->bmiHeader.biClrUsed = 0;
+   bwBIH->bmiHeader.biXPelsPerMeter = 0;
+   bwBIH->bmiHeader.biYPelsPerMeter = 0;
+
+   bwBIH->bmiColors[0].rgbBlue = 0;
+   bwBIH->bmiColors[0].rgbGreen = 0;
+   bwBIH->bmiColors[0].rgbRed = 0;
+   bwBIH->bmiColors[0].rgbReserved = 0;
+
+   bwBIH->bmiColors[1].rgbBlue = 0xff;
+   bwBIH->bmiColors[1].rgbGreen = 0xff;
+   bwBIH->bmiColors[1].rgbRed = 0xff;
+   bwBIH->bmiColors[1].rgbReserved = 0;
+
+   /* Load the AND bitmap */
+   IconInfo.hbmMask = CreateDIBitmap(hDC, &bwBIH->bmiHeader, 0,
+                                     XORImageData, bwBIH, DIB_RGB_COLORS);
+   if (IconInfo.hbmMask)
+   {
+      SetDIBits(hDC, IconInfo.hbmMask, 0, IconImage->icHeader.biHeight,
+                XORImageData, bwBIH, DIB_RGB_COLORS);
+   }
+
+   IconInfo.hbmColor = (HBITMAP)0;
+
+   /* Create the icon based on everything we have so far */
+   return NtUserCreateCursorIconHandle(&IconInfo, FALSE);
 }
 
 
@@ -161,7 +151,7 @@ CopyIcon(
   HICON hIcon)
 {
   ICONINFO IconInfo;
-  
+
   if(NtUserGetCursorIconInfo((HANDLE)hIcon, &IconInfo))
   {
     return NtUserCreateCursorIconHandle(&IconInfo, FALSE);
@@ -200,7 +190,7 @@ CreateIcon(
     DeleteObject(IconInfo.hbmMask);
     return (HICON)0;
   }
-  
+
   return NtUserCreateCursorIconHandle(&IconInfo, FALSE);
 }
 
@@ -213,7 +203,7 @@ STDCALL
 CreateIconFromResource(
   PBYTE presbits,
   DWORD dwResSize,
-  WINBOOL fIcon,
+  BOOL fIcon,
   DWORD dwVer)
 {
   return CreateIconFromResourceEx(presbits, dwResSize, fIcon, dwVer, 0, 0, 0);
@@ -228,7 +218,7 @@ STDCALL
 CreateIconFromResourceEx(
   PBYTE pbIconBits,
   DWORD cbIconBits,
-  WINBOOL fIcon,
+  BOOL fIcon,
   DWORD dwVersion,
   int cxDesired,
   int cyDesired,
@@ -242,7 +232,7 @@ CreateIconFromResourceEx(
   HDC hScreenDc;
   WORD wXHotspot;
   WORD wYHotspot;
-  
+
   /*
     FIXME - does win support LR_SHARED? According to msdn it does but we don't
             have useful information to identify the icon
@@ -269,13 +259,17 @@ CreateIconFromResourceEx(
     }
 
   /* get an safe copy of the icon data */
-  SafeIconImage = RtlAllocateHeap(RtlGetProcessHeap(), 0, cbIconBits);
+  SafeIconImage = RtlAllocateHeap(GetProcessHeap(), 0, cbIconBits);
+  if (SafeIconImage == NULL)
+    {
+      return NULL;
+    }
   memcpy(SafeIconImage, pbIconBits, cbIconBits);
-  
+
   /* take into acount the origonal height was for both the AND and XOR images */
   if(fIcon)
     SafeIconImage->icHeader.biHeight /= 2;
-  
+
   if (SafeIconImage->icHeader.biSize == sizeof(BITMAPCOREHEADER))
     {
       BITMAPCOREHEADER* Core = (BITMAPCOREHEADER*)SafeIconImage;
@@ -284,7 +278,7 @@ CreateIconFromResourceEx(
     }
   else
     {
-      ColourCount = (SafeIconImage->icHeader.biBitCount <= 8) ? 
+      ColourCount = (SafeIconImage->icHeader.biBitCount <= 8) ?
                        (1 << SafeIconImage->icHeader.biBitCount) : 0;
       HeaderSize = sizeof(BITMAPINFOHEADER) + ColourCount * sizeof(RGBQUAD);
     }
@@ -296,7 +290,7 @@ CreateIconFromResourceEx(
   hScreenDc = CreateCompatibleDC(NULL);
   if (hScreenDc == NULL)
     {
-      RtlFreeHeap(RtlGetProcessHeap(), 0, SafeIconImage);
+      RtlFreeHeap(GetProcessHeap(), 0, SafeIconImage);
       return(NULL);
     }
 
@@ -304,7 +298,8 @@ CreateIconFromResourceEx(
     hIcon = ICON_CreateIconFromData(hScreenDc, Data, SafeIconImage, cxDesired, cyDesired, wXHotspot, wYHotspot);
   else
     hIcon = ICON_CreateCursorFromData(hScreenDc, Data, SafeIconImage, cxDesired, cyDesired, wXHotspot, wYHotspot);
-  RtlFreeHeap(RtlGetProcessHeap(), 0, SafeIconImage);
+  RtlFreeHeap(GetProcessHeap(), 0, SafeIconImage);
+  DeleteDC(hScreenDc);
 
   return hIcon;
 }
@@ -335,7 +330,7 @@ CreateIconIndirect(PICONINFO IconInfo)
   {
     return (HICON)0;
   }
-  
+
   /* FIXME - i doubt this is right (monochrome cursors */
   /*if(ColorBitmap.bmWidth != MaskBitmap.bmWidth ||
      ColorBitmap.bmHeight != MaskBitmap.bmWidth)
@@ -343,7 +338,7 @@ CreateIconIndirect(PICONINFO IconInfo)
     SetLastError(ERROR_INVALID_PARAMETER);
     return (HICON)0;
   }*/
-  
+
   return (HICON)NtUserCreateCursorIconHandle(IconInfo, TRUE);
 }
 
@@ -351,19 +346,19 @@ CreateIconIndirect(PICONINFO IconInfo)
 /*
  * @implemented
  */
-WINBOOL
+BOOL
 STDCALL
 DestroyIcon(
   HICON hIcon)
 {
-  return (WINBOOL)NtUserDestroyCursorIcon((HANDLE)hIcon, 0);
+  return (BOOL)NtUserDestroyCursorIcon((HANDLE)hIcon, 0);
 }
 
 
 /*
  * @implemented
  */
-WINBOOL
+BOOL
 STDCALL
 DrawIcon(
   HDC hDC,
@@ -377,7 +372,7 @@ DrawIcon(
 /*
  * @implemented
  */
-WINBOOL
+BOOL
 STDCALL
 DrawIconEx(
   HDC hdc,
@@ -390,8 +385,8 @@ DrawIconEx(
   HBRUSH hbrFlickerFreeDraw,
   UINT diFlags)
 {
-  return (WINBOOL)NtUserDrawIconEx(hdc, xLeft, yTop, hIcon, cxWidth, cyWidth, 
-                                   istepIfAniCur, hbrFlickerFreeDraw, diFlags, 
+  return (BOOL)NtUserDrawIconEx(hdc, xLeft, yTop, hIcon, cxWidth, cyWidth,
+                                   istepIfAniCur, hbrFlickerFreeDraw, diFlags,
                                    0, 0);
 }
 
@@ -399,14 +394,14 @@ DrawIconEx(
 /*
  * @implemented
  */
-WINBOOL
+BOOL
 STDCALL
 GetIconInfo(
   HICON hIcon,
   PICONINFO IconInfo)
 {
   /* FIXME - copy bitmaps */
-  return (WINBOOL)NtUserGetCursorIconInfo((HANDLE)hIcon, IconInfo);
+  return (BOOL)NtUserGetCursorIconInfo((HANDLE)hIcon, IconInfo);
 }
 
 
@@ -443,7 +438,7 @@ int
 STDCALL
 LookupIconIdFromDirectory(
   PBYTE presbits,
-  WINBOOL fIcon)
+  BOOL fIcon)
 {
     return LookupIconIdFromDirectoryEx( presbits, fIcon,
           fIcon ? GetSystemMetrics(SM_CXICON) : GetSystemMetrics(SM_CXCURSOR),
@@ -464,7 +459,7 @@ CURSORICON_FindBestCursor( GRPCURSORICONDIR *dir, int width, int height, int col
         DPRINT("Empty directory!\n");
         return NULL;
     }
-    if (dir->idCount == 1) 
+    if (dir->idCount == 1)
       return &dir->idEntries[0];  /* No choice... */
 
     /* Find Best Fit */
@@ -504,7 +499,7 @@ CURSORICON_FindBestCursor( GRPCURSORICONDIR *dir, int width, int height, int col
 
 /* Ported from WINE20030408 */
 GRPCURSORICONDIRENTRY*
-CURSORICON_FindBestIcon( GRPCURSORICONDIR *dir, int width, int height, int colors)
+CURSORICON_FindBestIcon( GRPCURSORICONDIR *dir, int width, int height, int colorbits)
 {
     int i;
     GRPCURSORICONDIRENTRY *entry, *bestEntry = NULL;
@@ -542,7 +537,7 @@ CURSORICON_FindBestIcon( GRPCURSORICONDIR *dir, int width, int height, int color
         if(abs(width - entry->ResInfo.icon.bWidth) == (int) iXDiff &&
            abs(height - entry->ResInfo.icon.bHeight) == (int) iYDiff)
         {
-            iTempColorDiff = abs(colors - entry->ResInfo.icon.bColorCount);
+            iTempColorDiff = abs(colorbits - entry->wBitCount);
             if(iColorDiff > iTempColorDiff)
             {
                 bestEntry = entry;
@@ -558,47 +553,44 @@ CURSORICON_FindBestIcon( GRPCURSORICONDIR *dir, int width, int height, int color
 /*
  * @implemented
  */
-int
-STDCALL
+INT STDCALL
 LookupIconIdFromDirectoryEx(
   PBYTE presbits,
-  WINBOOL fIcon,
+  BOOL fIcon,
   int cxDesired,
   int cyDesired,
   UINT Flags)
 {
-    GRPCURSORICONDIR *dir = (GRPCURSORICONDIR*)presbits;
-    UINT retVal = 0;
+   GRPCURSORICONDIR *dir = (GRPCURSORICONDIR*)presbits;
+   UINT retVal = 0;
 
-    if( dir && !dir->idReserved && (dir->idType & 3) )
-    {
-       GRPCURSORICONDIRENTRY* entry;
-       HDC hdc;
-       UINT palEnts;
-       int colors;
-       hdc = GetDC(0);
-#if 0
-       palEnts = GetSystemPaletteEntries(hdc, 0, 0, NULL);
-       if (palEnts == 0)
-       palEnts = 256;
-#endif
-       palEnts = 16;  //use this until GetSystemPaletteEntries works
-       colors = (Flags & LR_MONOCHROME) ? 2 : palEnts;
-
-       ReleaseDC(0, hdc);
-
-       entry = (GRPCURSORICONDIRENTRY*)CURSORICON_FindBestIcon( dir,
-                                                          cxDesired,
-                                                          cyDesired,
-                                                          colors );
-
-       if( entry )
-           retVal = entry->nID;
-    }
-    else
-    {
+   if (dir && !dir->idReserved && (IMAGE_ICON == dir->idType || IMAGE_CURSOR == dir->idType))
+   {
+      GRPCURSORICONDIRENTRY *entry;
+      HDC hdc;
+      int ColorBits;
+
+      hdc = CreateICW(NULL, NULL, NULL, NULL);
+      if (Flags & LR_MONOCHROME)
+      {
+         ColorBits = 1;
+      }
+      else
+      {
+         ColorBits = GetDeviceCaps(hdc, BITSPIXEL);
+         if (ColorBits > 8)
+            ColorBits = 8;
+      }
+      DeleteDC(hdc);
+
+      entry = CURSORICON_FindBestIcon( dir, cxDesired, cyDesired, ColorBits );
+
+      if (entry)
+         retVal = entry->nID;
+   }
+   else
+   {
        DbgPrint("invalid resource directory\n");
-    }
-    return retVal;
+   }
+   return retVal;
 }
-