[USER32]
authorKamil Hornicek <kamil.hornicek@reactos.org>
Thu, 6 Nov 2014 23:28:28 +0000 (23:28 +0000)
committerKamil Hornicek <kamil.hornicek@reactos.org>
Thu, 6 Nov 2014 23:28:28 +0000 (23:28 +0000)
- use get_best_icon_file_entry's magic to find the correct icon in ICO_ExtractIconExW - thanks Jérôme!
- add cursor files support for PrivateExtractIcon(Ex)

svn path=/trunk/; revision=65303

reactos/win32ss/user/user32/misc/exticon.c
reactos/win32ss/user/user32/windows/cursoricon_new.c

index ddc683e..4254e48 100644 (file)
@@ -44,6 +44,16 @@ static void dumpIcoDir ( LPicoICONDIR entry )
 }
 #endif
 
+#ifndef WINE
+DWORD get_best_icon_file_offset(const LPBYTE dir,
+                                DWORD dwFileSize,
+                                int cxDesired,
+                                int cyDesired,
+                                BOOL bIcon,
+                                DWORD fuLoad,
+                                POINT *ptHotSpot);
+#endif 
+
 /**********************************************************************
  *  find_entry_by_id
  *
@@ -99,10 +109,10 @@ static DWORD USER32_GetResourceTable(LPBYTE peimage,DWORD pesize,LPBYTE *retptr)
 
        if (mz_header->e_magic != IMAGE_DOS_SIGNATURE)
        {
-         if (mz_header->e_cblp == 1)   /* .ICO file ? */
+         if (mz_header->e_cblp == 1 || mz_header->e_cblp == 2) /* .ICO or .CUR file ? */
          {
            *retptr = (LPBYTE)-1;       /* ICONHEADER.idType, must be 1 */
-           return 1;
+           return mz_header->e_cblp;
          }
          else
            return 0; /* failed */
@@ -361,36 +371,58 @@ static UINT ICO_ExtractIconExW(
          }
        }
 #else
-    if (sig == 1) /* .ICO file */
+    if (sig == 1 || sig == 2) /* .ICO or .CUR file */
     {
         TRACE("-- icon Signature (0x%08x)\n", sig);
 
         if (pData == (BYTE*)-1)
         {
-            INT dataOffset;
-            LPICONIMAGE entry;
-            CURSORICONDIR *lpcid = (CURSORICONDIR*)peimage;
             INT cx[2] = {cx1, cx2}, cy[2] = {cy1, cy2};
             INT index;
 
-            if (lpcid->idType != 1)
-                return 0;
-
             for(index = 0; index < 2; index++)
             {
-                dataOffset = LookupIconIdFromDirectoryEx(peimage, TRUE, cx[index], cy[index], flags);
+                DWORD dataOffset;
+                LPBYTE imageData;
+                POINT hotSpot;
+                LPICONIMAGE entry;
+
+                dataOffset = get_best_icon_file_offset(peimage, fsizel, cx[index], cy[index], sig == 1, flags, sig == 1 ? NULL : &hotSpot);
 
                 if (dataOffset)
                 {
                     HICON icon;
-                    entry = (LPICONIMAGE)(peimage + dataOffset);
-                    icon = CreateIconFromResourceEx(peimage + dataOffset, entry->icHeader.biSizeImage, TRUE, 0x00030000, cx[index], cy[index], flags);
+                    WORD *cursorData = NULL;
+
+                    imageData = peimage + dataOffset;
+                    entry = (LPICONIMAGE)(imageData);
+
+                    if(sig == 2)
+                    {
+                        /* we need to prepend the bitmap data with hot spots for CreateIconFromResourceEx */
+                        cursorData = HeapAlloc(GetProcessHeap(), 0, entry->icHeader.biSizeImage + 2 * sizeof(WORD));
+
+                        if(!cursorData)
+                            continue;
+
+                        cursorData[0] = hotSpot.x;
+                        cursorData[1] = hotSpot.y;
+
+                        memcpy(cursorData + 2, imageData, entry->icHeader.biSizeImage);
+
+                        imageData = (LPBYTE)cursorData;
+                    }
+
+                    icon = CreateIconFromResourceEx(imageData, entry->icHeader.biSizeImage, sig == 1, 0x00030000, cx[index], cy[index], flags);
 
                     if (icon)
                     {
                         RetPtr[index] = icon;
                         iconCount = 1;
                     }
+
+                    if(cursorData != NULL)
+                        HeapFree(GetProcessHeap(), 0, cursorData);
                 }
             }
 
index a20d2d7..747cf12 100644 (file)
@@ -436,7 +436,6 @@ typedef struct
 
 #include "poppack.h"
 
-static
 const CURSORICONFILEDIRENTRY*
 get_best_icon_file_entry(
     _In_ const CURSORICONFILEDIR* dir,
@@ -522,6 +521,33 @@ get_best_icon_file_entry(
     /* We found it */
     return &dir->idEntries[i-1];
 }
+
+DWORD
+get_best_icon_file_offset(
+    _In_ const LPBYTE dir,
+    _In_ DWORD dwFileSize,
+    _In_ int cxDesired,
+    _In_ int cyDesired,
+    _In_ BOOL bIcon,
+    _In_ DWORD fuLoad,
+    _Out_ POINT *ptHotSpot
+)
+{
+    const CURSORICONFILEDIRENTRY *entry;
+
+    entry = get_best_icon_file_entry((CURSORICONFILEDIR *) dir, dwFileSize, cxDesired, cyDesired, bIcon, fuLoad);
+
+    if(ptHotSpot)
+    {
+        ptHotSpot->x = entry->xHotspot;
+        ptHotSpot->y = entry->yHotspot;
+    }
+
+    if(entry)
+        return entry->dwDIBOffset;
+
+    return 0;
+}