https://git.reactos.org/?p=reactos.git;a=commitdiff;h=3e1a54151fdb2f513d5e1d...
commit 3e1a54151fdb2f513d5e1d4a374c2c973132493a Author: Jérôme Gardou jerome.gardou@reactos.org AuthorDate: Mon Oct 23 20:34:02 2017 +0200
[WIN32SS] - Do not call the driver Escape routine while holding locks on GDI objects CORE-7727 --- win32ss/gdi/eng/pdevobj.h | 7 ++ win32ss/gdi/eng/surface.h | 7 ++ win32ss/gdi/ntgdi/print.c | 179 ++++++++++++++++++++++++++-------------------- 3 files changed, 117 insertions(+), 76 deletions(-)
diff --git a/win32ss/gdi/eng/pdevobj.h b/win32ss/gdi/eng/pdevobj.h index 4fabfe135e..9b986acde1 100644 --- a/win32ss/gdi/eng/pdevobj.h +++ b/win32ss/gdi/eng/pdevobj.h @@ -201,4 +201,11 @@ PDEVOBJ_pdmMatchDevMode( PPDEVOBJ ppdev, PDEVMODEW pdm);
+FORCEINLINE +VOID +PDEVOBJ_vReference(PPDEVOBJ ppdev) +{ + InterlockedIncrement(&ppdev->cPdevRefs); +} + #endif /* !__WIN32K_PDEVOBJ_H */ diff --git a/win32ss/gdi/eng/surface.h b/win32ss/gdi/eng/surface.h index 96a35b13e6..ee05847e99 100644 --- a/win32ss/gdi/eng/surface.h +++ b/win32ss/gdi/eng/surface.h @@ -90,6 +90,13 @@ enum _SURFACEFLAGS /* NOTE: Use shared locks! */ #define SURFACE_ShareLockSurface(hBMObj) \ ((PSURFACE) GDIOBJ_ShareLockObj ((HGDIOBJ) hBMObj, GDI_OBJECT_TYPE_BITMAP)) +FORCEINLINE +VOID +SURFACE_ShareLockByPointer(PSURFACE psurf) +{ + GDIOBJ_vReferenceObjectByPointer(&psurf->BaseObject); +} + #define SURFACE_UnlockSurface(pBMObj) \ GDIOBJ_vUnlockObject ((POBJ)pBMObj) #define SURFACE_ShareUnlockSurface(pBMObj) \ diff --git a/win32ss/gdi/ntgdi/print.c b/win32ss/gdi/ntgdi/print.c index 5139eaa8ad..582bfcac1c 100644 --- a/win32ss/gdi/ntgdi/print.c +++ b/win32ss/gdi/ntgdi/print.c @@ -75,43 +75,6 @@ NtGdiEscape(HDC hDC, return ret; }
-INT -APIENTRY -IntGdiExtEscape( - PDC dc, - INT Escape, - INT InSize, - LPCSTR InData, - INT OutSize, - LPSTR OutData) -{ - SURFACE *psurf; - INT Result; - - if ((dc->ppdev->DriverFunctions.Escape == NULL) || - (dc->dclevel.pSurface == NULL)) - { - Result = 0; - } - else - { - DC_vPrepareDCsForBlit(dc, NULL, NULL, NULL); - psurf = dc->dclevel.pSurface; - - Result = dc->ppdev->DriverFunctions.Escape( - &psurf->SurfObj, - Escape, - InSize, - (PVOID)InData, - OutSize, - (PVOID)OutData ); - - DC_vFinishBlit(dc, NULL); - } - - return Result; -} - INT APIENTRY NtGdiExtEscape( @@ -124,22 +87,73 @@ NtGdiExtEscape( INT OutSize, OPTIONAL LPSTR UnsafeOutData) { - PDC pDC; LPVOID SafeInData = NULL; LPVOID SafeOutData = NULL; NTSTATUS Status = STATUS_SUCCESS; INT Result; + PPDEVOBJ ppdev; + PSURFACE psurf; + + if (hDC == NULL) + { + if (pDriver) + { + /* FIXME : Get the pdev from its name */ + UNIMPLEMENTED; + return -1; + }
- if (hDC == 0) + ppdev = EngpGetPDEV(NULL); + if (!ppdev) + { + EngSetLastError(ERROR_BAD_DEVICE); + return -1; + } + + /* We're using the primary surface of the pdev. Lock it */ + EngAcquireSemaphore(ppdev->hsemDevLock); + + psurf = ppdev->pSurface; + if (!psurf) + { + EngReleaseSemaphore(ppdev->hsemDevLock); + PDEVOBJ_vRelease(ppdev); + return 0; + } + SURFACE_ShareLockByPointer(psurf); + } + else { - hDC = UserGetWindowDC(NULL); + PDC pDC = DC_LockDc(hDC); + if ( pDC == NULL ) + { + EngSetLastError(ERROR_INVALID_HANDLE); + return -1; + } + + /* Get the PDEV from the DC */ + ppdev = pDC->ppdev; + PDEVOBJ_vReference(ppdev); + + /* Check if we have a surface */ + psurf = pDC->dclevel.pSurface; + if (!psurf) + { + DC_UnlockDc(pDC); + PDEVOBJ_vRelease(ppdev); + return 0; + } + SURFACE_ShareLockByPointer(psurf); + + /* We're done with the DC */ + DC_UnlockDc(pDC); }
- pDC = DC_LockDc(hDC); - if ( pDC == NULL ) + /* See if we actually have a driver function to call */ + if (ppdev->DriverFunctions.Escape == NULL) { - EngSetLastError(ERROR_INVALID_HANDLE); - return -1; + Result = 0; + goto Exit; }
if ( InSize && UnsafeInData ) @@ -158,17 +172,16 @@ NtGdiExtEscape(
if (!NT_SUCCESS(Status)) { - DC_UnlockDc(pDC); - SetLastNtError(Status); - return -1; + Result = -1; + goto Exit; }
SafeInData = ExAllocatePoolWithTag ( PagedPool, InSize, GDITAG_TEMP ); if ( !SafeInData ) { - DC_UnlockDc(pDC); EngSetLastError(ERROR_NOT_ENOUGH_MEMORY); - return -1; + Result = -1; + goto Exit; }
_SEH2_TRY @@ -186,10 +199,9 @@ NtGdiExtEscape(
if ( !NT_SUCCESS(Status) ) { - ExFreePoolWithTag ( SafeInData, GDITAG_TEMP ); - DC_UnlockDc(pDC); SetLastNtError(Status); - return -1; + Result = -1; + goto Exit; } }
@@ -209,50 +221,65 @@ NtGdiExtEscape(
if (!NT_SUCCESS(Status)) { - SetLastNtError(Status); - goto freeout; + SetLastNtError(Status); + Result = -1; + goto Exit; }
SafeOutData = ExAllocatePoolWithTag ( PagedPool, OutSize, GDITAG_TEMP ); if ( !SafeOutData ) { EngSetLastError(ERROR_NOT_ENOUGH_MEMORY); -freeout: - if ( SafeInData ) - ExFreePoolWithTag ( SafeInData, GDITAG_TEMP ); - DC_UnlockDc(pDC); - return -1; + Result = -1; + goto Exit; } }
- Result = IntGdiExtEscape ( pDC, Escape, InSize, SafeInData, OutSize, SafeOutData ); + /* Finally call the driver */ + Result = ppdev->DriverFunctions.Escape( + &psurf->SurfObj, + Escape, + InSize, + SafeInData, + OutSize, + SafeOutData );
- DC_UnlockDc(pDC); +Exit: + if (hDC == NULL) + { + EngReleaseSemaphore(ppdev->hsemDevLock); + } + SURFACE_ShareUnlockSurface(psurf); + PDEVOBJ_vRelease(ppdev);
if ( SafeInData ) + { ExFreePoolWithTag ( SafeInData ,GDITAG_TEMP ); + }
if ( SafeOutData ) { - _SEH2_TRY - { - /* Pointers were already probed! */ - RtlCopyMemory(UnsafeOutData, - SafeOutData, - OutSize); - } - _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + if (Result > 0) { - Status = _SEH2_GetExceptionCode(); + _SEH2_TRY + { + /* Pointers were already probed! */ + RtlCopyMemory(UnsafeOutData, SafeOutData, OutSize); + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + Status = _SEH2_GetExceptionCode(); + } + _SEH2_END; + + if ( !NT_SUCCESS(Status) ) + { + SetLastNtError(Status); + Result = -1; + } } - _SEH2_END;
ExFreePoolWithTag ( SafeOutData, GDITAG_TEMP ); - if ( !NT_SUCCESS(Status) ) - { - SetLastNtError(Status); - return -1; - } }
return Result;