mirror of
https://github.com/reactos/reactos.git
synced 2025-02-22 16:36:33 +00:00
[WIN32K]
- Pass bitmap buffer size to SURFACE_AllocSurface and validate it - Fix arithmetic overflow checks by using RtlULongMult - GreExtTextOutW: do not allocate / blit zero sized bitmaps - NtGdiStretchDIBitsInternal: do not pass negative y size to GreCreateBitmapEx - DIB_CreateDIBSection: use calculated bitmap size, instead of biSizeImage when calculating the section view size and as size parameter to GreCreateBitmapEx CORE-9245 #resolve svn path=/trunk/; revision=66611
This commit is contained in:
parent
15f19bca32
commit
ff14566384
8 changed files with 116 additions and 72 deletions
|
@ -1078,6 +1078,7 @@ IntEngMaskBlt(
|
|||
psoDest->iBitmapFormat,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
NULL);
|
||||
if (psurfTemp == NULL)
|
||||
{
|
||||
|
|
|
@ -120,6 +120,7 @@ SURFACE_AllocSurface(
|
|||
_In_ ULONG iFormat,
|
||||
_In_ ULONG fjBitmap,
|
||||
_In_opt_ ULONG cjWidth,
|
||||
_In_opt_ ULONG cjBufSize,
|
||||
_In_opt_ PVOID pvBits)
|
||||
{
|
||||
ULONG cBitsPixel, cjBits, cjObject;
|
||||
|
@ -127,7 +128,9 @@ SURFACE_AllocSurface(
|
|||
SURFOBJ *pso;
|
||||
PVOID pvSection;
|
||||
|
||||
ASSERT(!pvBits || (iType == STYPE_BITMAP));
|
||||
NT_ASSERT(!pvBits || (iType == STYPE_BITMAP));
|
||||
NT_ASSERT((iFormat <= BMF_32BPP) || (cjBufSize != 0));
|
||||
NT_ASSERT((LONG)cy > 0);
|
||||
|
||||
/* Verify format */
|
||||
if ((iFormat < BMF_1BPP) || (iFormat > BMF_PNG))
|
||||
|
@ -151,8 +154,35 @@ SURFACE_AllocSurface(
|
|||
cjWidth = WIDTH_BYTES_ALIGN32(cx, cBitsPixel);
|
||||
}
|
||||
|
||||
/* Calculate the bitmap size in bytes */
|
||||
cjBits = cjWidth * cy;
|
||||
/* Is this an uncompressed format? */
|
||||
if (iFormat <= BMF_32BPP)
|
||||
{
|
||||
/* Calculate the correct bitmap size in bytes */
|
||||
if (!NT_SUCCESS(RtlULongMult(cjWidth, cy, &cjBits)))
|
||||
{
|
||||
DPRINT1("Overflow calculating size: cjWidth %lu, cy %lu\n",
|
||||
cjWidth, cy);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Did we get a buffer and size? */
|
||||
if ((pvBits != NULL) && (cjBufSize != 0))
|
||||
{
|
||||
/* Make sure the buffer is large enough */
|
||||
if (cjBufSize < cjBits)
|
||||
{
|
||||
DPRINT1("Buffer is too small, required: %lu, got %lu\n",
|
||||
cjBits, cjBufSize);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Compressed format, use the provided size */
|
||||
NT_ASSERT(cjBufSize != 0);
|
||||
cjBits = cjBufSize;
|
||||
}
|
||||
|
||||
/* Check if we need an extra large object */
|
||||
if ((iType == STYPE_BITMAP) && (pvBits == NULL) &&
|
||||
|
@ -168,9 +198,10 @@ SURFACE_AllocSurface(
|
|||
}
|
||||
|
||||
/* Check for arithmetic overflow */
|
||||
if ((cjBits < cjWidth) || (cjObject < sizeof(SURFACE)))
|
||||
if (cjObject < sizeof(SURFACE))
|
||||
{
|
||||
/* Fail! */
|
||||
DPRINT1("Overflow calculating cjObject: cjBits %lu\n", cjBits);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -289,6 +320,7 @@ EngCreateBitmap(
|
|||
iFormat,
|
||||
fl,
|
||||
lWidth,
|
||||
0,
|
||||
pvBits);
|
||||
if (!psurf)
|
||||
{
|
||||
|
@ -327,6 +359,7 @@ EngCreateDeviceBitmap(
|
|||
iFormat,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
NULL);
|
||||
if (!psurf)
|
||||
{
|
||||
|
@ -365,6 +398,7 @@ EngCreateDeviceSurface(
|
|||
iFormat,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
NULL);
|
||||
if (!psurf)
|
||||
{
|
||||
|
|
|
@ -123,6 +123,7 @@ SURFACE_AllocSurface(
|
|||
_In_ ULONG iFormat,
|
||||
_In_ ULONG fjBitmap,
|
||||
_In_opt_ ULONG cjWidth,
|
||||
_In_opt_ ULONG cjBits,
|
||||
_In_opt_ PVOID pvBits);
|
||||
|
||||
FORCEINLINE
|
||||
|
|
|
@ -1453,6 +1453,7 @@ NtGdiGetPixel(
|
|||
BMF_32BPP,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
&ulRGBColor);
|
||||
if (psurfDest)
|
||||
{
|
||||
|
|
|
@ -103,6 +103,7 @@ GreCreateBitmapEx(
|
|||
pvCompressedBits = pvBits;
|
||||
pvBits = NULL;
|
||||
iFormat = (iFormat == BMF_4RLE) ? BMF_4BPP : BMF_8BPP;
|
||||
cjSizeImage = 0;
|
||||
}
|
||||
|
||||
/* Allocate a surface */
|
||||
|
@ -112,6 +113,7 @@ GreCreateBitmapEx(
|
|||
iFormat,
|
||||
fjBitmap,
|
||||
cjWidthBytes,
|
||||
cjSizeImage,
|
||||
pvBits);
|
||||
if (!psurf)
|
||||
{
|
||||
|
@ -207,6 +209,7 @@ NtGdiCreateBitmap(
|
|||
iFormat,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
NULL);
|
||||
if (!psurf)
|
||||
{
|
||||
|
|
|
@ -1090,7 +1090,7 @@ NtGdiGetDIBitsInternal(
|
|||
_SEH2_TRY
|
||||
{
|
||||
/* Copy the data back */
|
||||
cjMaxInfo = min(cjMaxInfo, DIB_BitmapInfoSize(pbmi, (WORD)iUsage));
|
||||
cjMaxInfo = min(cjMaxInfo, (UINT)DIB_BitmapInfoSize(pbmi, (WORD)iUsage));
|
||||
ProbeForWrite(pbmiUser, cjMaxInfo, 1);
|
||||
RtlCopyMemory(pbmiUser, pbmi, cjMaxInfo);
|
||||
}
|
||||
|
@ -1228,7 +1228,7 @@ NtGdiStretchDIBitsInternal(
|
|||
RECTL_vOffsetRect(&rcDst, pdc->ptlDCOrig.x, pdc->ptlDCOrig.y);
|
||||
|
||||
hbmTmp = GreCreateBitmapEx(pbmi->bmiHeader.biWidth,
|
||||
pbmi->bmiHeader.biHeight,
|
||||
abs(pbmi->bmiHeader.biHeight),
|
||||
0,
|
||||
BitmapFormat(pbmi->bmiHeader.biBitCount,
|
||||
pbmi->bmiHeader.biCompression),
|
||||
|
@ -1652,7 +1652,7 @@ DIB_CreateDIBSection(
|
|||
|
||||
// Get storage location for DIB bits. Only use biSizeImage if it's valid and
|
||||
// we're dealing with a compressed bitmap. Otherwise, use width * height.
|
||||
totalSize = bi->biSizeImage && bi->biCompression != BI_RGB && bi->biCompression != BI_BITFIELDS
|
||||
totalSize = (bi->biSizeImage && (bi->biCompression != BI_RGB) && (bi->biCompression != BI_BITFIELDS))
|
||||
? bi->biSizeImage : (ULONG)(bm.bmWidthBytes * effHeight);
|
||||
|
||||
if (section)
|
||||
|
@ -1674,7 +1674,7 @@ DIB_CreateDIBSection(
|
|||
}
|
||||
|
||||
mapOffset = offset - (offset % Sbi.AllocationGranularity);
|
||||
mapSize = bi->biSizeImage + (offset - mapOffset);
|
||||
mapSize = totalSize + (offset - mapOffset);
|
||||
|
||||
SectionOffset.LowPart = mapOffset;
|
||||
SectionOffset.HighPart = 0;
|
||||
|
@ -1724,7 +1724,7 @@ DIB_CreateDIBSection(
|
|||
BitmapFormat(bi->biBitCount * bi->biPlanes, bi->biCompression),
|
||||
BMF_DONTCACHE | BMF_USERMEM | BMF_NOZEROINIT |
|
||||
((bi->biHeight < 0) ? BMF_TOPDOWN : 0),
|
||||
bi->biSizeImage,
|
||||
totalSize,
|
||||
bm.bmBits,
|
||||
0);
|
||||
if (!res)
|
||||
|
|
|
@ -3662,7 +3662,6 @@ GreExtTextOutW(
|
|||
ROP4_FROM_INDEX(R3_OPINDEX_PATCOPY));
|
||||
MouseSafetyOnDrawEnd(dc->ppdev);
|
||||
BackgroundLeft = DestRect.right;
|
||||
|
||||
}
|
||||
|
||||
DestRect.left = ((TextLeft + 32) >> 6) + realglyph->left;
|
||||
|
@ -3675,72 +3674,76 @@ GreExtTextOutW(
|
|||
MaskRect.right = realglyph->bitmap.width;
|
||||
MaskRect.bottom = realglyph->bitmap.rows;
|
||||
|
||||
/*
|
||||
* We should create the bitmap out of the loop at the biggest possible
|
||||
* glyph size. Then use memset with 0 to clear it and sourcerect to
|
||||
* limit the work of the transbitblt.
|
||||
*/
|
||||
/* Check if the bitmap has any pixels */
|
||||
if ((bitSize.cx != 0) && (bitSize.cy != 0))
|
||||
{
|
||||
/*
|
||||
* We should create the bitmap out of the loop at the biggest possible
|
||||
* glyph size. Then use memset with 0 to clear it and sourcerect to
|
||||
* limit the work of the transbitblt.
|
||||
*/
|
||||
|
||||
HSourceGlyph = EngCreateBitmap(bitSize, realglyph->bitmap.pitch,
|
||||
BMF_8BPP, BMF_TOPDOWN,
|
||||
realglyph->bitmap.buffer);
|
||||
if ( !HSourceGlyph )
|
||||
{
|
||||
DPRINT1("WARNING: EngLockSurface() failed!\n");
|
||||
// FT_Done_Glyph(realglyph);
|
||||
IntUnLockFreeType;
|
||||
DC_vFinishBlit(dc, NULL);
|
||||
goto fail2;
|
||||
}
|
||||
SourceGlyphSurf = EngLockSurface((HSURF)HSourceGlyph);
|
||||
if ( !SourceGlyphSurf )
|
||||
{
|
||||
HSourceGlyph = EngCreateBitmap(bitSize, realglyph->bitmap.pitch,
|
||||
BMF_8BPP, BMF_TOPDOWN,
|
||||
realglyph->bitmap.buffer);
|
||||
if ( !HSourceGlyph )
|
||||
{
|
||||
DPRINT1("WARNING: EngCreateBitmap() failed!\n");
|
||||
// FT_Done_Glyph(realglyph);
|
||||
IntUnLockFreeType;
|
||||
DC_vFinishBlit(dc, NULL);
|
||||
goto fail2;
|
||||
}
|
||||
SourceGlyphSurf = EngLockSurface((HSURF)HSourceGlyph);
|
||||
if ( !SourceGlyphSurf )
|
||||
{
|
||||
EngDeleteSurface((HSURF)HSourceGlyph);
|
||||
DPRINT1("WARNING: EngLockSurface() failed!\n");
|
||||
IntUnLockFreeType;
|
||||
DC_vFinishBlit(dc, NULL);
|
||||
goto fail2;
|
||||
}
|
||||
|
||||
/*
|
||||
* Use the font data as a mask to paint onto the DCs surface using a
|
||||
* brush.
|
||||
*/
|
||||
|
||||
if (lprc && (fuOptions & ETO_CLIPPED) &&
|
||||
DestRect.right >= lprc->right + dc->ptlDCOrig.x)
|
||||
{
|
||||
// We do the check '>=' instead of '>' to possibly save an iteration
|
||||
// through this loop, since it's breaking after the drawing is done,
|
||||
// and x is always incremented.
|
||||
DestRect.right = lprc->right + dc->ptlDCOrig.x;
|
||||
DoBreak = TRUE;
|
||||
}
|
||||
if (lprc && (fuOptions & ETO_CLIPPED) &&
|
||||
DestRect.bottom >= lprc->bottom + dc->ptlDCOrig.y)
|
||||
{
|
||||
DestRect.bottom = lprc->bottom + dc->ptlDCOrig.y;
|
||||
}
|
||||
MouseSafetyOnDrawStart(dc->ppdev, DestRect.left, DestRect.top, DestRect.right, DestRect.bottom);
|
||||
if (!IntEngMaskBlt(
|
||||
SurfObj,
|
||||
SourceGlyphSurf,
|
||||
&dc->co.ClipObj,
|
||||
&exloRGB2Dst.xlo,
|
||||
&exloDst2RGB.xlo,
|
||||
&DestRect,
|
||||
(PPOINTL)&MaskRect,
|
||||
&dc->eboText.BrushObject,
|
||||
&BrushOrigin))
|
||||
{
|
||||
DPRINT1("Failed to MaskBlt a glyph!\n");
|
||||
}
|
||||
|
||||
MouseSafetyOnDrawEnd(dc->ppdev) ;
|
||||
|
||||
EngUnlockSurface(SourceGlyphSurf);
|
||||
EngDeleteSurface((HSURF)HSourceGlyph);
|
||||
DPRINT1("WARNING: EngLockSurface() failed!\n");
|
||||
IntUnLockFreeType;
|
||||
DC_vFinishBlit(dc, NULL);
|
||||
goto fail2;
|
||||
}
|
||||
|
||||
/*
|
||||
* Use the font data as a mask to paint onto the DCs surface using a
|
||||
* brush.
|
||||
*/
|
||||
|
||||
if (lprc && (fuOptions & ETO_CLIPPED) &&
|
||||
DestRect.right >= lprc->right + dc->ptlDCOrig.x)
|
||||
{
|
||||
// We do the check '>=' instead of '>' to possibly save an iteration
|
||||
// through this loop, since it's breaking after the drawing is done,
|
||||
// and x is always incremented.
|
||||
DestRect.right = lprc->right + dc->ptlDCOrig.x;
|
||||
DoBreak = TRUE;
|
||||
}
|
||||
if (lprc && (fuOptions & ETO_CLIPPED) &&
|
||||
DestRect.bottom >= lprc->bottom + dc->ptlDCOrig.y)
|
||||
{
|
||||
DestRect.bottom = lprc->bottom + dc->ptlDCOrig.y;
|
||||
}
|
||||
MouseSafetyOnDrawStart(dc->ppdev, DestRect.left, DestRect.top, DestRect.right, DestRect.bottom);
|
||||
if (!IntEngMaskBlt(
|
||||
SurfObj,
|
||||
SourceGlyphSurf,
|
||||
&dc->co.ClipObj,
|
||||
&exloRGB2Dst.xlo,
|
||||
&exloDst2RGB.xlo,
|
||||
&DestRect,
|
||||
(PPOINTL)&MaskRect,
|
||||
&dc->eboText.BrushObject,
|
||||
&BrushOrigin))
|
||||
{
|
||||
DPRINT1("Failed to MaskBlt a glyph!\n");
|
||||
}
|
||||
|
||||
MouseSafetyOnDrawEnd(dc->ppdev) ;
|
||||
|
||||
EngUnlockSurface(SourceGlyphSurf);
|
||||
EngDeleteSurface((HSURF)HSourceGlyph);
|
||||
|
||||
if (DoBreak)
|
||||
{
|
||||
break;
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include <ndk/psfuncs.h>
|
||||
#include <ndk/rtlfuncs.h>
|
||||
#include <ntstrsafe.h>
|
||||
#include <ntintsafe.h>
|
||||
#include <ntddkbd.h>
|
||||
|
||||
/* Win32 headers */
|
||||
|
|
Loading…
Reference in a new issue