Author: tkreuzer Date: Fri Aug 27 10:57:54 2010 New Revision: 48630
URL: http://svn.reactos.org/svn/reactos?rev=48630&view=rev Log: [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.
Modified: trunk/reactos/subsystems/win32/win32k/eng/mouse.c
Modified: trunk/reactos/subsystems/win32/win32k/eng/mouse.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/eng... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/eng/mouse.c [iso-8859-1] (original) +++ trunk/reactos/subsystems/win32/win32k/eng/mouse.c [iso-8859-1] Fri Aug 27 10:57:54 2010 @@ -208,6 +208,9 @@ }
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; @@ -318,42 +321,117 @@ { 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 @@ pgp->psurfColor = NULL; }
+ /* Free old mask bitmap */ if (pgp->psurfMask) { EngDeleteSurface(pgp->psurfMask->BaseObject.hHmgr); @@ -368,7 +447,8 @@ 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 @@ /* 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 @@ }
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; }
/*