https://git.reactos.org/?p=reactos.git;a=commitdiff;h=3e1a54151fdb2f513d5e1…
commit 3e1a54151fdb2f513d5e1d4a374c2c973132493a
Author: Jérôme Gardou <jerome.gardou(a)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;