http://bugs.winehq.org/show_bug.cgi?id=6439
------- Additional Comments From a_villacis@palosanto.com 2006-20-10 17:42 ------- Created an attachment (id=3900) --> (http://bugs.winehq.org/attachment.cgi?id=3900&action=view) Patch to prevent the use of CreateCompatibleDC at GetDIBits (try 1)
(quoting myself from wine-devel)
The only users of _CheckNotSysLevel in the Wine tree are dlls/user and dll/gdi . In dlls/user the pattern seems to be to use USER_Lock() and USER_Unlock() in strict pairs to protect blocks of code and not call any other functions that use USER_CheckNotLock(). In dlls/gdi the lock is taken once every time a reference to a GDI object is requested, but the rule about not calling other functions that check GDI_CheckNotLock() can be violated (at least in my bug) on the rendering of a metafile, as shown by the sequence:
(App tries to draw an icon into a metafile) DrawIconEx calls into StretchBlt (dlls/gdi/bitblt.c:140) StretchBlt calls DC_GetDCUpdate, then DC_GetDCPtr . Both of these functions increment the GDI lock, so it ends up with a lock count of (at least) 2. (dlls/gdi/bitblt.c:148) With lock held, StretchBlt calls into dcDst->funcs->pStretchBlt. Since this is a metafile, it calls into EMFDRV_StretchBlt (dlls/gdi/enhmfdrv/bitblt.c:186) EMFDRV_StretchBlt delegates to EMFDRV_BitBlockTransfer (dlls/gdi/enhmfdrv/bitblt.c:163) EMFDRV_BitBlockTransfer calls into GetDIBits <-- possible source of bug? (dlls/gdi/dib.c:556) GetDIBits calls CreateCompatibleDC with the source HDC (dlls/gdi/dc.c:728) CreateCompatibleDC() calls into GDI_CheckNotLock unconditionally. But StretchBlt already raised the lock count --> debug assertion.
So, when metafiles are involved, this sequence of calls triggers the debug assertion in CreateCompatibleDC().
(quote from Alexandre Julliard)
Yes, and the assertion should remain there. The real bug is that GetDIBits creates a new DC, it shouldn't need to do that.
This is the first attempt at a patch that will fix the debug assertion when icons are rendered into metafiles (triggered by Enterprise Architect 6.5, and possibly others). This patch simply removes mentions of memdc, created by a call to CreateCompatibleDC(), and redirects calls to GetDIBColorTable() to use the original DC instead of memdc.