From 3a325683bc8747512a25e4be8319eb7221e99612 Mon Sep 17 00:00:00 2001 From: Timo Kreuzer Date: Fri, 27 Aug 2010 10:57:54 +0000 Subject: [PATCH] [WIN32K] - Rework EngSetPointerShape, to first allocate the neccessary surfaces, before deleting the old ones. Also check in IntShowMousePointer if a saving surface is present. This way a failure to allocate a surface will not result in a crash, but keep the old mouse pointer. See issue #5402 for more details. svn path=/trunk/; revision=48630 --- reactos/subsystems/win32/win32k/eng/mouse.c | 230 +++++++++++--------- 1 file changed, 122 insertions(+), 108 deletions(-) diff --git a/reactos/subsystems/win32/win32k/eng/mouse.c b/reactos/subsystems/win32/win32k/eng/mouse.c index f5f6b2f30ca..93ab14d4f6d 100644 --- a/reactos/subsystems/win32/win32k/eng/mouse.c +++ b/reactos/subsystems/win32/win32k/eng/mouse.c @@ -209,6 +209,9 @@ IntShowMousePointer(PDEVOBJ *ppdev, SURFOBJ *psoDest) pgp->Enabled = TRUE; + /* Check if we have any mouse pointer */ + if (!pgp->psurfSave) return; + /* Calculate pointer coordinates */ pt.x = ppdev->ptlPointer.x - pgp->HotSpot.x; pt.y = ppdev->ptlPointer.y - pgp->HotSpot.y; @@ -318,42 +321,117 @@ EngSetPointerShape( { PDEVOBJ *ppdev; GDIPOINTER *pgp; - LONG lDelta; - HBITMAP hbmp; - RECTL rcl; + LONG lDelta = 0; + HBITMAP hbmSave = NULL, hbmColor = NULL, hbmMask = NULL; + PSURFACE psurfSave = NULL, psurfColor = NULL, psurfMask = NULL; + RECTL rectl; + SIZEL sizel = {0, 0}; ASSERT(pso); ppdev = GDIDEV(pso); pgp = &ppdev->Pointer; + /* Do we have any bitmap at all? */ + if (psoColor || psoMask) + { + /* Get the size of the new pointer */ + if (psoColor) + { + sizel.cx = psoColor->sizlBitmap.cx; + sizel.cy = psoColor->sizlBitmap.cy; + } + else// if (psoMask) + { + sizel.cx = psoMask->sizlBitmap.cx; + sizel.cy = psoMask->sizlBitmap.cy / 2; + } + + rectl.left = 0; + rectl.top = 0; + rectl.right = sizel.cx; + rectl.bottom = sizel.cy; + + /* Calculate lDelta for our surfaces. */ + lDelta = DIB_GetDIBWidthBytes(sizel.cx, + BitsPerFormat(pso->iBitmapFormat)); + + /* Create a bitmap for saving the pixels under the cursor. */ + hbmSave = EngCreateBitmap(sizel, + lDelta, + pso->iBitmapFormat, + BMF_TOPDOWN | BMF_NOZEROINIT, + NULL); + psurfSave = SURFACE_ShareLockSurface(hbmSave); + if (!psurfSave) goto failure; + } + if (psoColor) { - pgp->Size.cx = psoColor->sizlBitmap.cx; - pgp->Size.cy = psoColor->sizlBitmap.cy; - if (psoMask) - { - // CHECKME: Is this really required? if we have a color surface, - // we only need the AND part of the mask. - /* Check if the sizes match as they should */ - if (psoMask->sizlBitmap.cx != psoColor->sizlBitmap.cx || - psoMask->sizlBitmap.cy != psoColor->sizlBitmap.cy * 2) - { - DPRINT("Sizes of mask (%ld,%ld) and color (%ld,%ld) don't match\n", - psoMask->sizlBitmap.cx, psoMask->sizlBitmap.cy, - psoColor->sizlBitmap.cx, psoColor->sizlBitmap.cy); -// return SPS_ERROR; - } - } - } - else if (psoMask) - { - pgp->Size.cx = psoMask->sizlBitmap.cx; - pgp->Size.cy = psoMask->sizlBitmap.cy / 2; + /* Color bitmap must have the same format as the dest surface */ + if (psoColor->iBitmapFormat != pso->iBitmapFormat) goto failure; + + /* Create a bitmap to copy the color bitmap to */ + hbmColor = EngCreateBitmap(psoColor->sizlBitmap, + lDelta, + pso->iBitmapFormat, + BMF_TOPDOWN | BMF_NOZEROINIT, + NULL); + psurfColor = SURFACE_ShareLockSurface(hbmColor); + if (!psurfColor) goto failure; + + /* Now copy the given bitmap */ + rectl.bottom = psoColor->sizlBitmap.cy; + IntEngCopyBits(&psurfColor->SurfObj, + psoColor, + NULL, + pxlo, + &rectl, + (POINTL*)&rectl); } + /* Create a mask surface */ + if (psoMask) + { + EXLATEOBJ exlo; + PPALETTE ppal; + + /* Create a bitmap for the mask */ + hbmMask = EngCreateBitmap(psoMask->sizlBitmap, + lDelta, + pso->iBitmapFormat, + BMF_TOPDOWN | BMF_NOZEROINIT, + NULL); + psurfMask = SURFACE_ShareLockSurface(hbmMask); + if (!psurfMask) goto failure; + + /* Initialize an EXLATEOBJ */ + ppal = PALETTE_LockPalette(ppdev->devinfo.hpalDefault); + EXLATEOBJ_vInitialize(&exlo, + &gpalMono, + ppal, + 0, + RGB(0xff,0xff,0xff), + RGB(0,0,0)); + + /* Copy the mask bitmap */ + rectl.bottom = psoMask->sizlBitmap.cy; + IntEngCopyBits(&psurfMask->SurfObj, + psoMask, + NULL, + &exlo.xlo, + &rectl, + (POINTL*)&rectl); + + /* Cleanup */ + EXLATEOBJ_vCleanup(&exlo); + if (ppal) PALETTE_UnlockPalette(ppal); + } + + /* Hide mouse pointer */ IntHideMousePointer(ppdev, pso); + /* Free old color bitmap */ if (pgp->psurfColor) { EngDeleteSurface(pgp->psurfColor->BaseObject.hHmgr); @@ -361,6 +439,7 @@ EngSetPointerShape( pgp->psurfColor = NULL; } + /* Free old mask bitmap */ if (pgp->psurfMask) { EngDeleteSurface(pgp->psurfMask->BaseObject.hHmgr); @@ -368,7 +447,8 @@ EngSetPointerShape( pgp->psurfMask = NULL; } - if (pgp->psurfSave != NULL) + /* Free old save bitmap */ + if (pgp->psurfSave) { EngDeleteSurface(pgp->psurfSave->BaseObject.hHmgr); SURFACE_ShareUnlockSurface(pgp->psurfSave); @@ -378,94 +458,17 @@ EngSetPointerShape( /* See if we are being asked to hide the pointer. */ if (psoMask == NULL && psoColor == NULL) { + /* We're done */ return SPS_ACCEPT_NOEXCLUDE; } + /* Now set the new cursor */ + pgp->psurfColor = psurfColor; + pgp->psurfMask = psurfMask; + pgp->psurfSave = psurfSave; pgp->HotSpot.x = xHot; pgp->HotSpot.y = yHot; - - /* Calculate lDelta for our surfaces. */ - lDelta = DIB_GetDIBWidthBytes(pgp->Size.cx, - BitsPerFormat(pso->iBitmapFormat)); - - rcl.left = 0; - rcl.top = 0; - rcl.right = pgp->Size.cx; - rcl.bottom = pgp->Size.cy; - - /* Create surface for saving the pixels under the cursor. */ - hbmp = EngCreateBitmap(pgp->Size, - lDelta, - pso->iBitmapFormat, - BMF_TOPDOWN | BMF_NOZEROINIT, - NULL); - pgp->psurfSave = SURFACE_ShareLockSurface(hbmp); - - /* Create a mask surface */ - if (psoMask) - { - EXLATEOBJ exlo; - PPALETTE ppal; - - hbmp = EngCreateBitmap(psoMask->sizlBitmap, - lDelta, - pso->iBitmapFormat, - BMF_TOPDOWN | BMF_NOZEROINIT, - NULL); - pgp->psurfMask = SURFACE_ShareLockSurface(hbmp); - - if(pgp->psurfMask) - { - ppal = PALETTE_LockPalette(ppdev->devinfo.hpalDefault); - EXLATEOBJ_vInitialize(&exlo, - &gpalMono, - ppal, - 0, - RGB(0xff,0xff,0xff), - RGB(0,0,0)); - - rcl.bottom = psoMask->sizlBitmap.cy; - IntEngCopyBits(&pgp->psurfMask->SurfObj, - psoMask, - NULL, - &exlo.xlo, - &rcl, - (POINTL*)&rcl); - - EXLATEOBJ_vCleanup(&exlo); - if (ppal) - PALETTE_UnlockPalette(ppal); - } - } - else - { - pgp->psurfMask = NULL; - } - - /* Create a color surface */ - if (psoColor) - { - hbmp = EngCreateBitmap(psoColor->sizlBitmap, - lDelta, - pso->iBitmapFormat, - BMF_TOPDOWN | BMF_NOZEROINIT, - NULL); - pgp->psurfColor = SURFACE_ShareLockSurface(hbmp); - if (pgp->psurfColor) - { - rcl.bottom = psoColor->sizlBitmap.cy; - IntEngCopyBits(&pgp->psurfColor->SurfObj, - psoColor, - NULL, - pxlo, - &rcl, - (POINTL*)&rcl); - } - } - else - { - pgp->psurfColor = NULL; - } + pgp->Size = sizel; if (x != -1) { @@ -488,6 +491,17 @@ EngSetPointerShape( } return SPS_ACCEPT_NOEXCLUDE; + +failure: + /* Cleanup surfaces */ + if (hbmMask) EngDeleteSurface(hbmMask); + if (psurfMask) SURFACE_ShareUnlockSurface(psurfMask); + if (hbmColor) EngDeleteSurface(hbmColor); + if (psurfColor) SURFACE_ShareUnlockSurface(psurfColor); + if (hbmSave) EngDeleteSurface(hbmSave); + if (psurfSave) SURFACE_ShareUnlockSurface(psurfSave); + + return SPS_ERROR; } /*