[PATCH 07/11] winemac: Use unixlib interface for macdrv_app_icon.

Jacek Caban wine at gitlab.winehq.org
Thu Jun 2 19:51:22 CDT 2022


From: Jacek Caban <jacek at codeweavers.com>

Signed-off-by: Jacek Caban <jacek at codeweavers.com>
---
 dlls/winemac.drv/dllmain.c | 168 ++++++++++++++++++++++++++++++++++
 dlls/winemac.drv/image.c   | 178 ++++++-------------------------------
 dlls/winemac.drv/unixlib.h |  25 +++++-
 3 files changed, 219 insertions(+), 152 deletions(-)

diff --git a/dlls/winemac.drv/dllmain.c b/dlls/winemac.drv/dllmain.c
index 675820b28cd..e281a473e07 100644
--- a/dlls/winemac.drv/dllmain.c
+++ b/dlls/winemac.drv/dllmain.c
@@ -63,6 +63,30 @@ static BOOL CALLBACK get_process_windows(HWND hwnd, LPARAM lp)
     return TRUE;
 }
 
+#include "pshpack1.h"
+
+typedef struct
+{
+    BYTE bWidth;
+    BYTE bHeight;
+    BYTE bColorCount;
+    BYTE bReserved;
+    WORD wPlanes;
+    WORD wBitCount;
+    DWORD dwBytesInRes;
+    WORD nID;
+} GRPICONDIRENTRY;
+
+typedef struct
+{
+    WORD idReserved;
+    WORD idType;
+    WORD idCount;
+    GRPICONDIRENTRY idEntries[1];
+} GRPICONDIR;
+
+#include "poppack.h"
+
 static void quit_reply(int reply)
 {
     struct quit_result_params params = { .result = reply };
@@ -199,9 +223,153 @@ fail:
     return 0;
 }
 
+/***********************************************************************
+ *              get_first_resource
+ *
+ * Helper for create_app_icon_images().  Enum proc for EnumResourceNamesW()
+ * which just gets the handle for the first resource and stops further
+ * enumeration.
+ */
+static BOOL CALLBACK get_first_resource(HMODULE module, LPCWSTR type, LPWSTR name, LONG_PTR lparam)
+{
+    HRSRC *res_info = (HRSRC*)lparam;
+
+    *res_info = FindResourceW(module, name, (LPCWSTR)RT_GROUP_ICON);
+    return FALSE;
+}
+
+
+/***********************************************************************
+ *              macdrv_app_icon
+ */
+static NTSTATUS WINAPI macdrv_app_icon(void *arg, ULONG size)
+{
+    struct app_icon_params *params = arg;
+    struct app_icon_result *result = params->result;
+    HRSRC res_info;
+    HGLOBAL res_data;
+    GRPICONDIR *icon_dir;
+    int i;
+
+    TRACE("()\n");
+
+    result->count = 0;
+
+    res_info = NULL;
+    EnumResourceNamesW(NULL, (LPCWSTR)RT_GROUP_ICON, get_first_resource, (LONG_PTR)&res_info);
+    if (!res_info)
+    {
+        WARN("found no RT_GROUP_ICON resource\n");
+        return 0;
+    }
+
+    if (!(res_data = LoadResource(NULL, res_info)))
+    {
+        WARN("failed to load RT_GROUP_ICON resource\n");
+        return 0;
+    }
+
+    if (!(icon_dir = LockResource(res_data)))
+    {
+        WARN("failed to lock RT_GROUP_ICON resource\n");
+        goto cleanup;
+    }
+
+    for (i = 0; i < icon_dir->idCount && result->count < ARRAYSIZE(result->entries); i++)
+    {
+        struct app_icon_entry *entry = &result->entries[result->count];
+        int width = icon_dir->idEntries[i].bWidth;
+        int height = icon_dir->idEntries[i].bHeight;
+        BOOL found_better_bpp = FALSE;
+        int j;
+        LPCWSTR name;
+        HGLOBAL icon_res_data;
+        BYTE *icon_bits;
+
+        if (!width) width = 256;
+        if (!height) height = 256;
+
+        /* If there's another icon at the same size but with better
+           color depth, skip this one.  We end up making CGImages that
+           are all 32 bits per pixel, so Cocoa doesn't get the original
+           color depth info to pick the best representation itself. */
+        for (j = 0; j < icon_dir->idCount; j++)
+        {
+            int jwidth = icon_dir->idEntries[j].bWidth;
+            int jheight = icon_dir->idEntries[j].bHeight;
+
+            if (!jwidth) jwidth = 256;
+            if (!jheight) jheight = 256;
+
+            if (j != i && jwidth == width && jheight == height &&
+                icon_dir->idEntries[j].wBitCount > icon_dir->idEntries[i].wBitCount)
+            {
+                found_better_bpp = TRUE;
+                break;
+            }
+        }
+
+        if (found_better_bpp) continue;
+
+        name = MAKEINTRESOURCEW(icon_dir->idEntries[i].nID);
+        res_info = FindResourceW(NULL, name, (LPCWSTR)RT_ICON);
+        if (!res_info)
+        {
+            WARN("failed to find RT_ICON resource %d with ID %hd\n", i, icon_dir->idEntries[i].nID);
+            continue;
+        }
+
+        icon_res_data = LoadResource(NULL, res_info);
+        if (!icon_res_data)
+        {
+            WARN("failed to load icon %d with ID %hd\n", i, icon_dir->idEntries[i].nID);
+            continue;
+        }
+
+        icon_bits = LockResource(icon_res_data);
+        if (icon_bits)
+        {
+            static const BYTE png_magic[] = { 0x89, 0x50, 0x4e, 0x47 };
+
+            entry->width = width;
+            entry->height = height;
+            entry->size = icon_dir->idEntries[i].dwBytesInRes;
+
+            if (!memcmp(icon_bits, png_magic, sizeof(png_magic)))
+            {
+                entry->png = icon_bits;
+                entry->icon = 0;
+                result->count++;
+            }
+            else
+            {
+                entry->icon = CreateIconFromResourceEx(icon_bits, icon_dir->idEntries[i].dwBytesInRes,
+                                                       TRUE, 0x00030000, width, height, 0);
+                if (entry->icon)
+                {
+                    entry->png = NULL;
+                    result->count++;
+                }
+                else
+                    WARN("failed to create icon %d from resource with ID %hd\n", i, icon_dir->idEntries[i].nID);
+            }
+        }
+        else
+            WARN("failed to lock RT_ICON resource %d with ID %hd\n", i, icon_dir->idEntries[i].nID);
+
+        FreeResource(icon_res_data);
+    }
+
+cleanup:
+    FreeResource(res_data);
+
+    return 0;
+}
+
 typedef NTSTATUS (WINAPI *kernel_callback)(void *params, ULONG size);
 static const kernel_callback kernel_callbacks[] =
 {
+    macdrv_app_icon,
     macdrv_app_quit_request,
     macdrv_dnd_query_drag,
     macdrv_dnd_query_drop,
diff --git a/dlls/winemac.drv/image.c b/dlls/winemac.drv/image.c
index 943ad97b749..f6423858136 100644
--- a/dlls/winemac.drv/image.c
+++ b/dlls/winemac.drv/image.c
@@ -25,30 +25,6 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(image);
 
-#include "pshpack1.h"
-
-typedef struct
-{
-    BYTE bWidth;
-    BYTE bHeight;
-    BYTE bColorCount;
-    BYTE bReserved;
-    WORD wPlanes;
-    WORD wBitCount;
-    DWORD dwBytesInRes;
-    WORD nID;
-} GRPICONDIRENTRY;
-
-typedef struct
-{
-    WORD idReserved;
-    WORD idType;
-    WORD idCount;
-    GRPICONDIRENTRY idEntries[1];
-} GRPICONDIR;
-
-#include "poppack.h"
-
 
 /***********************************************************************
  *              create_cgimage_from_icon_bitmaps
@@ -264,167 +240,67 @@ cleanup:
 }
 
 
-/***********************************************************************
- *              get_first_resource
- *
- * Helper for create_app_icon_images().  Enum proc for EnumResourceNamesW()
- * which just gets the handle for the first resource and stops further
- * enumeration.
- */
-static BOOL CALLBACK get_first_resource(HMODULE module, LPCWSTR type, LPWSTR name, LONG_PTR lparam)
-{
-    HRSRC *res_info = (HRSRC*)lparam;
-
-    *res_info = FindResourceW(module, name, (LPCWSTR)RT_GROUP_ICON);
-    return FALSE;
-}
-
-
 /***********************************************************************
  *              create_app_icon_images
  */
 CFArrayRef create_app_icon_images(void)
 {
-    HRSRC res_info;
-    HGLOBAL res_data;
-    GRPICONDIR *icon_dir;
+    struct app_icon_result icons;
+    struct app_icon_params params = { .result = &icons };
     CFMutableArrayRef images = NULL;
     int i;
 
     TRACE("()\n");
 
-    res_info = NULL;
-    EnumResourceNamesW(NULL, (LPCWSTR)RT_GROUP_ICON, get_first_resource, (LONG_PTR)&res_info);
-    if (!res_info)
-    {
-        WARN("found no RT_GROUP_ICON resource\n");
-        return NULL;
-    }
+    macdrv_client_func(client_func_app_icon, &params, sizeof(params));
 
-    if (!(res_data = LoadResource(NULL, res_info)))
-    {
-        WARN("failed to load RT_GROUP_ICON resource\n");
-        return NULL;
-    }
+    if (!icons.count) return NULL;
 
-    if (!(icon_dir = LockResource(res_data)))
-    {
-        WARN("failed to lock RT_GROUP_ICON resource\n");
-        goto cleanup;
-    }
-
-    images = CFArrayCreateMutable(NULL, icon_dir->idCount, &kCFTypeArrayCallBacks);
+    images = CFArrayCreateMutable(NULL, icons.count, &kCFTypeArrayCallBacks);
     if (!images)
     {
         WARN("failed to create images array\n");
-        goto cleanup;
+        return NULL;
     }
 
-    for (i = 0; i < icon_dir->idCount; i++)
+    for (i = 0; i < icons.count; i++)
     {
-        int width = icon_dir->idEntries[i].bWidth;
-        int height = icon_dir->idEntries[i].bHeight;
-        BOOL found_better_bpp = FALSE;
-        int j;
-        LPCWSTR name;
-        HGLOBAL icon_res_data;
-        BYTE *icon_bits;
-
-        if (!width) width = 256;
-        if (!height) height = 256;
-
-        /* If there's another icon at the same size but with better
-           color depth, skip this one.  We end up making CGImages that
-           are all 32 bits per pixel, so Cocoa doesn't get the original
-           color depth info to pick the best representation itself. */
-        for (j = 0; j < icon_dir->idCount; j++)
-        {
-            int jwidth = icon_dir->idEntries[j].bWidth;
-            int jheight = icon_dir->idEntries[j].bHeight;
-
-            if (!jwidth) jwidth = 256;
-            if (!jheight) jheight = 256;
+        struct app_icon_entry *icon = &icons.entries[i];
+        CGImageRef cgimage = NULL;
 
-            if (j != i && jwidth == width && jheight == height &&
-                icon_dir->idEntries[j].wBitCount > icon_dir->idEntries[i].wBitCount)
-            {
-                found_better_bpp = TRUE;
-                break;
-            }
-        }
-
-        if (found_better_bpp) continue;
-
-        name = MAKEINTRESOURCEW(icon_dir->idEntries[i].nID);
-        res_info = FindResourceW(NULL, name, (LPCWSTR)RT_ICON);
-        if (!res_info)
+        if (icon->png)
         {
-            WARN("failed to find RT_ICON resource %d with ID %hd\n", i, icon_dir->idEntries[i].nID);
-            continue;
-        }
-
-        icon_res_data = LoadResource(NULL, res_info);
-        if (!icon_res_data)
-        {
-            WARN("failed to load icon %d with ID %hd\n", i, icon_dir->idEntries[i].nID);
-            continue;
-        }
-
-        icon_bits = LockResource(icon_res_data);
-        if (icon_bits)
-        {
-            static const BYTE png_magic[] = { 0x89, 0x50, 0x4e, 0x47 };
-            CGImageRef cgimage = NULL;
-
-            if (!memcmp(icon_bits, png_magic, sizeof(png_magic)))
-            {
-                CFDataRef data = CFDataCreate(NULL, (UInt8*)icon_bits, icon_dir->idEntries[i].dwBytesInRes);
-                if (data)
-                {
-                    CGDataProviderRef provider = CGDataProviderCreateWithCFData(data);
-                    CFRelease(data);
-                    if (provider)
-                    {
-                        cgimage = CGImageCreateWithPNGDataProvider(provider, NULL, FALSE,
-                                                                   kCGRenderingIntentDefault);
-                        CGDataProviderRelease(provider);
-                    }
-                }
-            }
-
-            if (!cgimage)
+            CFDataRef data = CFDataCreate(NULL, icon->png, icon->size);
+            if (data)
             {
-                HICON icon;
-                icon = CreateIconFromResourceEx(icon_bits, icon_dir->idEntries[i].dwBytesInRes,
-                                                TRUE, 0x00030000, width, height, 0);
-                if (icon)
+                CGDataProviderRef provider = CGDataProviderCreateWithCFData(data);
+                CFRelease(data);
+                if (provider)
                 {
-                    cgimage = create_cgimage_from_icon(icon, width, height);
-                    DestroyIcon(icon);
+                    cgimage = CGImageCreateWithPNGDataProvider(provider, NULL, FALSE,
+                                                               kCGRenderingIntentDefault);
+                    CGDataProviderRelease(provider);
                 }
-                else
-                    WARN("failed to create icon %d from resource with ID %hd\n", i, icon_dir->idEntries[i].nID);
-            }
-
-            if (cgimage)
-            {
-                CFArrayAppendValue(images, cgimage);
-                CGImageRelease(cgimage);
             }
         }
         else
-            WARN("failed to lock RT_ICON resource %d with ID %hd\n", i, icon_dir->idEntries[i].nID);
+        {
+            cgimage = create_cgimage_from_icon(icon->icon, icon->width, icon->height);
+            NtUserDestroyCursor(icon->icon, 0);
+        }
 
-        FreeResource(icon_res_data);
+        if (cgimage)
+        {
+            CFArrayAppendValue(images, cgimage);
+            CGImageRelease(cgimage);
+        }
     }
 
-cleanup:
     if (images && !CFArrayGetCount(images))
     {
         CFRelease(images);
         images = NULL;
     }
-    FreeResource(res_data);
 
     return images;
 }
diff --git a/dlls/winemac.drv/unixlib.h b/dlls/winemac.drv/unixlib.h
index 894ab699c13..fea59564b92 100644
--- a/dlls/winemac.drv/unixlib.h
+++ b/dlls/winemac.drv/unixlib.h
@@ -102,7 +102,8 @@ struct quit_result_params
 /* driver client callbacks exposed with KernelCallbackTable interface */
 enum macdrv_client_funcs
 {
-    client_func_app_quit_request = NtUserDriverCallbackFirst,
+    client_func_app_icon = NtUserDriverCallbackFirst,
+    client_func_app_quit_request,
     client_func_dnd_query_drag,
     client_func_dnd_query_drop,
     client_func_dnd_query_exited,
@@ -111,6 +112,28 @@ enum macdrv_client_funcs
     client_func_last
 };
 
+/* macdrv_app_icon result */
+struct app_icon_entry
+{
+    UINT32 width;
+    UINT32 height;
+    UINT32 size;
+    void *png;
+    HICON icon;
+};
+
+struct app_icon_result
+{
+    UINT32 count;
+    struct app_icon_entry entries[64];
+};
+
+/* macdrv_app_icon params */
+struct app_icon_params
+{
+    struct app_icon_result *result; /* FIXME: Use NtCallbackReturn instead */
+};
+
 /* macdrv_app_quit_request params */
 struct app_quit_request_params
 {
-- 
GitLab


https://gitlab.winehq.org/wine/wine/-/merge_requests/177



More information about the wine-devel mailing list