https://bugs.winehq.org/show_bug.cgi?id=52207
Bug ID: 52207 Summary: HICON leak in CopyImage Product: Wine Version: 6.21 Hardware: x86-64 OS: Linux Status: UNCONFIRMED Severity: normal Priority: P2 Component: user32 Assignee: wine-bugs@winehq.org Reporter: jswinebz@kanargh.org.uk Distribution: ---
Created attachment 71264 --> https://bugs.winehq.org/attachment.cgi?id=71264 Don't leak HICONs from CopyImage
At some point between 6.7 and 6.21, user32.CopyImage was reworked.
In the IMAGE_ICON, LR_COPYFROMRESOURCE case it used to just call CURSORICON_Load and return its return value.
Now it calls CURSORICON_Load, makes *another* copy of that (in case it wants to resize it, but it still creates another copy if it's already the right size), then returns the copy. The original intermediate HICON is leaked. This also leaks its two underlying GDI HBITMAPs. Since there are two HBITMAPs for each HICON, we run out of GDI handles first.
(I run The Bat! as my email client, which animates its systray icon when there is unread mail. The leaking HICONs cause it to crash after just under 2 hours, which is roughly what 5fps at two handles per frame takes to hit 65536.)
The attached patch fixes that by fudging LR_COPYDELETEORG into the flags for that case, causing the "original" (actually our intermediate) icon to be deleted on exit...
...except there's a second bug there. As it stands it tries to use gdi32.DeleteObject to delete the HICON. But DeleteObject can only delete GDI handles (for example the two embedded HBITMAPs within the HICON), but the HICON itself is a user object and the delete fails.
So the DeleteObject call must also be changed to DestroyIcon to make that work.
With both of those changes in, the GDI handle count is now stable.