From 103f78276b844c0dcf653ad99a0e0e78b054f63a Mon Sep 17 00:00:00 2001 From: FunkyFr3sh Date: Mon, 27 May 2024 05:01:54 +0200 Subject: [PATCH] make clipper threadsafe for TA --- inc/IDirectDrawClipper.h | 1 + src/IDirectDraw/IDirectDrawClipper.c | 2 ++ src/ddclipper.c | 48 ++++++++++++++++++++++++++++ 3 files changed, 51 insertions(+) diff --git a/inc/IDirectDrawClipper.h b/inc/IDirectDrawClipper.h index 7e5161f..95510e6 100644 --- a/inc/IDirectDrawClipper.h +++ b/inc/IDirectDrawClipper.h @@ -16,6 +16,7 @@ typedef struct IDirectDrawClipperImpl ULONG ref; HWND hwnd; HRGN region; + CRITICAL_SECTION cs; } IDirectDrawClipperImpl; diff --git a/src/IDirectDraw/IDirectDrawClipper.c b/src/IDirectDraw/IDirectDrawClipper.c index 86aaaa6..b07390f 100644 --- a/src/IDirectDraw/IDirectDrawClipper.c +++ b/src/IDirectDraw/IDirectDrawClipper.c @@ -31,6 +31,8 @@ ULONG __stdcall IDirectDrawClipper__Release(IDirectDrawClipperImpl* This) if (This->region) DeleteObject(This->region); + DeleteCriticalSection(&This->cs); + HeapFree(GetProcessHeap(), 0, This); } diff --git a/src/ddclipper.c b/src/ddclipper.c index 5d67f28..14ec412 100644 --- a/src/ddclipper.c +++ b/src/ddclipper.c @@ -7,11 +7,19 @@ HRESULT ddc_GetClipList(IDirectDrawClipperImpl* This, LPRECT lpRect, LPRGNDATA lpClipList, LPDWORD lpdwSiz) { + EnterCriticalSection(&This->cs); + if (!This->region) + { + LeaveCriticalSection(&This->cs); return DDERR_NOCLIPLIST; + } if (!lpdwSiz) + { + LeaveCriticalSection(&This->cs); return DDERR_INVALIDPARAMS; + } HRGN region = NULL; @@ -20,11 +28,16 @@ HRESULT ddc_GetClipList(IDirectDrawClipperImpl* This, LPRECT lpRect, LPRGNDATA l region = CreateRectRgnIndirect(lpRect); if (!region) + { + LeaveCriticalSection(&This->cs); return DDERR_INVALIDPARAMS; + } if (CombineRgn(region, This->region, region, RGN_AND) == ERROR) { DeleteObject(region); + + LeaveCriticalSection(&This->cs); return DDERR_GENERIC; } } @@ -39,40 +52,64 @@ HRESULT ddc_GetClipList(IDirectDrawClipperImpl* This, LPRECT lpRect, LPRGNDATA l DeleteObject(region); if (*lpdwSiz == 0) + { + LeaveCriticalSection(&This->cs); return DDERR_REGIONTOOSMALL; + } + LeaveCriticalSection(&This->cs); return DD_OK; } HRESULT ddc_GetHWnd(IDirectDrawClipperImpl* This, HWND FAR* lphWnd) { + EnterCriticalSection(&This->cs); + if (!lphWnd) + { + LeaveCriticalSection(&This->cs); return DDERR_INVALIDPARAMS; + } *lphWnd = This->hwnd; + LeaveCriticalSection(&This->cs); return DD_OK; } HRESULT ddc_IsClipListChanged(IDirectDrawClipperImpl* This, BOOL FAR* lpbChanged) { + EnterCriticalSection(&This->cs); + if (!lpbChanged) + { + LeaveCriticalSection(&This->cs); return DDERR_INVALIDPARAMS; + } *lpbChanged = FALSE; /* Always return FALSE - See ddc_SetHWnd for remarks */ + LeaveCriticalSection(&This->cs); return DD_OK; } HRESULT ddc_SetClipList(IDirectDrawClipperImpl* This, LPRGNDATA lpClipList, DWORD dwFlags) { + EnterCriticalSection(&This->cs); + if (This->hwnd) + { + LeaveCriticalSection(&This->cs); return DDERR_CLIPPERISUSINGHWND; + } if (lpClipList) { if (!lpClipList->rdh.nCount) + { + LeaveCriticalSection(&This->cs); return DDERR_INVALIDCLIPLIST; + } if (This->region) DeleteObject(This->region); @@ -82,14 +119,20 @@ HRESULT ddc_SetClipList(IDirectDrawClipperImpl* This, LPRGNDATA lpClipList, DWOR This->region = CreateRectRgnIndirect(&rc[0]); if (!This->region) + { + LeaveCriticalSection(&This->cs); return DDERR_INVALIDCLIPLIST; + } for (int i = 1; i < lpClipList->rdh.nCount; ++i) { HRGN region = CreateRectRgnIndirect(&rc[i]); if (!region) + { + LeaveCriticalSection(&This->cs); return DDERR_INVALIDCLIPLIST; + } if (CombineRgn(This->region, region, This->region, RGN_OR) == ERROR) { @@ -97,6 +140,7 @@ HRESULT ddc_SetClipList(IDirectDrawClipperImpl* This, LPRGNDATA lpClipList, DWOR DeleteObject(This->region); This->region = NULL; + LeaveCriticalSection(&This->cs); return DDERR_INVALIDCLIPLIST; } @@ -111,17 +155,20 @@ HRESULT ddc_SetClipList(IDirectDrawClipperImpl* This, LPRGNDATA lpClipList, DWOR This->region = NULL; } + LeaveCriticalSection(&This->cs); return DD_OK; } HRESULT ddc_SetHWnd(IDirectDrawClipperImpl* This, DWORD dwFlags, HWND hWnd) { + EnterCriticalSection(&This->cs); /* We don't use the regions from the hwnd here since everything is emulated and we need the entire emulated surface to be redrawn all the time */ This->hwnd = hWnd; + LeaveCriticalSection(&This->cs); return DD_OK; } @@ -137,6 +184,7 @@ HRESULT dd_CreateClipper(DWORD dwFlags, IDirectDrawClipperImpl** lplpDDClipper, c->lpVtbl = &g_ddc_vtbl; IDirectDrawClipper_AddRef(c); + InitializeCriticalSection(&c->cs); *lplpDDClipper = c;