It's not sufficient to make g_renderingRefCount atomic, because after it is
found to be nonzero in beginGdiRendering, a call to endGdiRendering from
another thread may make it zero before beginGdiRendering has a chance of
entering the critical section. This would mean that the DirectDraw primary
surface is no longer locked, even though beginGdiRendering expects that it is.
To prevent potential issues, the g_renderingRefCount check is now also
guarded by the critical section.
GetWindowDC(GetDC(NULL)) may return a special window with a class name of
"CompatWindowDesktopReplacement". Presumably the shim engine installs an
IAT hook for GetWindowDC that replaces this window handle with the normal
desktop window handle.
CALL_ORIG_FUNC(WindowFromDC) returns with an unpatched pointer, therefore
it doesn't perform the above replacement. This results in using the
replacement window's clipping region (whole screen) instead of the desktop
window's clipping region (empty), and things become visible that shouldn't
be, e.g. some character symbols at the top left corner of the screen when
launchning Diablo II.
As a workaround, WindowFromDC is used without CALL_ORIG_FUNC.
Using flip for direct front buffer updates can cause performance problems
if the driver forces vertical sync and overrides the DDFLIP_NOVSYNC flag.
On the other hand, DDFLIP_NOVSYNC flip requests on the compat primary
surface should be handled via real flip to allow vertical sync override.
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.