Scenario:
Thread #1 enters the DirectDraw critical section
Thread #2 enters the GDI critical section
Thread #2 starts waiting on the DirectDraw critical section
Thread #1 starts waiting on the GDI critical section
Solution:
If the primary surface has not been locked yet, enter the DirectDraw critical
section before entering the GDI critical section.
Immersive context menus don't display correctly when theming is disabled:
all menu items have empty labels and no icons.
Disabled this menu style through a faked registry value.
Now size box rendering works correctly, so no need for that workaround in
CompatGdiScrollBar.
There seems to be a bug with subclassing scroll bars though, as the cursor
will no longer change to a sizing arrow when it's over a size box control.
At least there is a simple workaround for that via WM_SETCURSOR.
Fixed in issue with adjusting the game speed slider in StarCraft's Battle.net interface.
It was resulting in a WM_HSCROLL message erasing the parent window background without also
redrawing the child windows (labels) on it.
Because both the DirectDraw and GDI thread locks are held by the thread that
initially calls beginGdiRendering, a deadlock can occur if a complex rendering
operation uses synchronized worker threads for some subtasks and they also need
access to the resources locked by the initial thread.
To resolve this, the GDI thread lock is no longer held after beginGdiRendering
returns, and the DirectDraw thread lock is only taken during the initial entry.
However, this introduces another problem, because now the final endGdiRendering
might not be called by the same thread that initially called beginGdiRendering.
If this happens, a deadlock will occur because the initial thread is still
holding the DirectDraw thread lock while the other thread is trying to acquire
it to unlock the primary surface.
To resolve this, the initial thread will always be the one to release the lock
on the primary surface, waiting for other threads to finish using GDI DCs if
necessary. This also means that other threads won't be able to create new
cached DCs (as they would need the DD thread lock), so to prevent yet another
deadlock, the initial thread always preallocates a number of DCs in the cache,
and only the initial thread is allowed to extend the cache.
Disabled visual styles and added WM_NCPAINT handling (as a simple BitBlt copy
from the original DC) to reduce glitches in rendering of common controls and
windows, such as the GetSaveFileName dialog window in StarCraft.
Fixed a deadlock in the caret emulation code caused by locking the GDI
critical section prior to calling beginGdiRendering, which is locking both the
DirectDraw and GDI critical sections. Another thread that only calls
beginGdiRendering without entering the GDI critical section first could thus
run into a deadlock as both threads were waiting on each other's critical
sections.
Now the global caret data has it its own critical section instead of sharing
the GDI critical section.