[PATCH 0/2] MR10382: comctl32/imagelist: Limit maximum image count.
Some applications mistakenly use a very large initial image count. On Windows, there is no limit on how large an imagelist can be. This makes sure that the GDI handle limit will be reached before hitting the imagelist limit. Supersedes https://gitlab.winehq.org/wine/wine/-/merge_requests/10059 -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10382
From: Kun Yang <yangkun@uniontech.com> Signed-off-by: Kun Yang <yangkun@uniontech.com> --- dlls/comctl32/tests/imagelist.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/dlls/comctl32/tests/imagelist.c b/dlls/comctl32/tests/imagelist.c index 68ad0ce7a4c..c2b04f622a4 100644 --- a/dlls/comctl32/tests/imagelist.c +++ b/dlls/comctl32/tests/imagelist.c @@ -2204,6 +2204,8 @@ static void test_iconsize(void) static void test_create_destroy(void) { HIMAGELIST himl; + IMAGEINFO info; + HBITMAP hbm; INT cx, cy; BOOL rc; INT ret; @@ -2263,6 +2265,19 @@ static void test_create_destroy(void) ok(himl == NULL, "got %p\n", himl); himl = pImageList_Create(1, -1, ILC_COLORDDB, 4, 4); ok(himl == NULL, "got %p\n", himl); + + /* Test creating an imagelist with an excessively large initial image count */ + himl = pImageList_Create(32, 32, ILC_COLOR32, 0xc0c0c0, 10); + ok(himl != NULL, "got %p\n", himl); + hbm = create_bitmap(32, 32, 0, ""); + ret = pImageList_Add(himl, hbm, NULL); + ok(ret != -1, "Failed to add an image.\n"); + ret = pImageList_GetImageInfo(himl, 0, &info); + ok(ret, "got %d\n", ret); + todo_wine + ok(info.hbmImage != NULL, "got %p\n", info.hbmImage); + DeleteObject(hbm); + pImageList_Destroy(himl); } static void check_color_table(const char *name, HDC hdc, HIMAGELIST himl, UINT ilc, -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10382
From: Zhiyi Zhang <zzhang@codeweavers.com> Some applications mistakenly use a very large initial image count. On Windows, there is no limit on how large an imagelist can be. This makes sure that the GDI handle limit will be reached before hitting the imagelist limit. --- dlls/comctl32/imagelist.c | 6 ++++++ dlls/comctl32/tests/imagelist.c | 1 - 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/dlls/comctl32/imagelist.c b/dlls/comctl32/imagelist.c index ba340645db8..1d76cec81e7 100644 --- a/dlls/comctl32/imagelist.c +++ b/dlls/comctl32/imagelist.c @@ -39,6 +39,7 @@ #include "winbase.h" #include "objbase.h" #include "wingdi.h" +#include "ntgdi.h" #include "winuser.h" #include "commctrl.h" #include "comctl32.h" @@ -3663,6 +3664,11 @@ static HRESULT WINAPI ImageListImpl_Initialize(IImageList2 *iface, INT cx, INT c grow = 256; } + /* Some applications mistakenly use a very large initial image count. On Windows, there is no + * limit of how large a imagelist can be. This makes sure that GDI handle limit will be reached + * before hitting the imagelist limit */ + initial = min(initial, GDI_MAX_HANDLE_COUNT); + himl->cx = cx; himl->cy = cy; himl->flags = flags; diff --git a/dlls/comctl32/tests/imagelist.c b/dlls/comctl32/tests/imagelist.c index c2b04f622a4..1921567627f 100644 --- a/dlls/comctl32/tests/imagelist.c +++ b/dlls/comctl32/tests/imagelist.c @@ -2274,7 +2274,6 @@ static void test_create_destroy(void) ok(ret != -1, "Failed to add an image.\n"); ret = pImageList_GetImageInfo(himl, 0, &info); ok(ret, "got %d\n", ret); - todo_wine ok(info.hbmImage != NULL, "got %p\n", info.hbmImage); DeleteObject(hbm); pImageList_Destroy(himl); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10382
This merge request was approved by Zhiyi Zhang. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10382
Nikolay Sivov (@nsivov) commented about dlls/comctl32/imagelist.c:
grow = 256; }
+ /* Some applications mistakenly use a very large initial image count. On Windows, there is no + * limit of how large a imagelist can be. This makes sure that GDI handle limit will be reached + * before hitting the imagelist limit */ + initial = min(initial, GDI_MAX_HANDLE_COUNT); + himl->cx = cx;
What does image count have to do with gdi handle count? -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10382#note_132821
On Thu Mar 19 14:50:24 2026 +0000, Nikolay Sivov wrote:
What does image count have to do with gdi handle count? Because you need to add a HBITMAP to the imagelist?
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/10382#note_132823
On Thu Mar 19 14:55:29 2026 +0000, Zhiyi Zhang wrote:
Because you need to add a HBITMAP to the imagelist? I think native can use any limit. For example, it can only initialise the first 1000 images, even if the caller uses a very large number.
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/10382#note_132825
On Thu Mar 19 14:57:07 2026 +0000, Zhiyi Zhang wrote:
I think native can use any limit. For example, it can only initialise the first 1000 images, even if the caller uses a very large number. I don't follow. We don't add a separate HBITMAP for every added image, do we?
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/10382#note_132826
On Thu Mar 19 14:59:40 2026 +0000, Nikolay Sivov wrote:
I don't follow. We don't add a separate HBITMAP for every added image, do we? Oh, right. It's just something weird that I noticed when I tested ImageList_Add(). Adding the same HBITMAP handle into the imagelist doesn't increase memory usage at all. But yeah, maybe we should pick something else.
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/10382#note_132828
On Thu Mar 19 15:19:29 2026 +0000, Zhiyi Zhang wrote:
Oh, right. It's just something weird that I noticed when I tested ImageList_Add(). Adding the same HBITMAP handle into the imagelist doesn't increase memory usage at all. But yeah, maybe we should pick something else. We can change IMAGELIST_InternalExpandBitmaps() to grow more conservatively.
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/10382#note_132829
participants (4)
-
Kun Yang -
Nikolay Sivov (@nsivov) -
Zhiyi Zhang -
Zhiyi Zhang (@zhiyi)