- In BitmapFormat, allow intermediate bpp values, use ULONG as parameter type, instead of WORD and DWORD
- In NtGdiCreateBitmap get the real bpp value from the gajBitsPerFormat array
- Add back check of too large nWidth (needed to make sure, cjWidthBytes didn't overflow)
- Merge all parameter checks
- Check cPlanes and cBitsPixel paramters explicitly
- Use GreCreateBitmapEx
- Remove BITMAP_GetRealBitsPixel

svn path=/trunk/; revision=50343
This commit is contained in:
Timo Kreuzer 2011-01-09 18:38:41 +00:00
parent 3ecc17156e
commit 39b87b357f
4 changed files with 29 additions and 71 deletions

View file

@ -37,28 +37,19 @@ gajBitsPerFormat[11] =
}; };
ULONG FASTCALL BitmapFormat(WORD Bits, DWORD Compression) ULONG FASTCALL BitmapFormat(ULONG cBits, ULONG iCompression)
{ {
switch (Compression) switch (iCompression)
{ {
case BI_RGB: case BI_RGB:
/* Fall through */ /* Fall through */
case BI_BITFIELDS: case BI_BITFIELDS:
switch (Bits) if (cBits <= 1) return BMF_1BPP;
{ if (cBits <= 4) return BMF_4BPP;
case 1: if (cBits <= 8) return BMF_8BPP;
return BMF_1BPP; if (cBits <= 16) return BMF_16BPP;
case 4: if (cBits <= 24) return BMF_24BPP;
return BMF_4BPP; if (cBits <= 32) return BMF_32BPP;
case 8:
return BMF_8BPP;
case 16:
return BMF_16BPP;
case 24:
return BMF_24BPP;
case 32:
return BMF_32BPP;
}
return 0; return 0;
case BI_RLE4: case BI_RLE4:

View file

@ -11,7 +11,6 @@ typedef struct tagBITMAPV5INFO
INT APIENTRY BITMAP_GetObject(SURFACE * bmp, INT count, LPVOID buffer); INT APIENTRY BITMAP_GetObject(SURFACE * bmp, INT count, LPVOID buffer);
HBITMAP FASTCALL IntCreateBitmap(IN SIZEL Size, IN LONG Width, IN ULONG Format, IN ULONG Flags, IN PVOID Bits); HBITMAP FASTCALL IntCreateBitmap(IN SIZEL Size, IN LONG Width, IN ULONG Format, IN ULONG Flags, IN PVOID Bits);
HBITMAP FASTCALL BITMAP_CopyBitmap (HBITMAP hBitmap); HBITMAP FASTCALL BITMAP_CopyBitmap (HBITMAP hBitmap);
UINT FASTCALL BITMAP_GetRealBitsPixel(UINT nBitsPixel);
HBITMAP HBITMAP
APIENTRY APIENTRY

View file

@ -125,7 +125,7 @@ SURFACE_bSetBitmapBits(
#define GDIDEV(SurfObj) ((PDEVOBJ *)((SurfObj)->hdev)) #define GDIDEV(SurfObj) ((PDEVOBJ *)((SurfObj)->hdev))
#define GDIDEVFUNCS(SurfObj) ((PDEVOBJ *)((SurfObj)->hdev))->DriverFunctions #define GDIDEVFUNCS(SurfObj) ((PDEVOBJ *)((SurfObj)->hdev))->DriverFunctions
ULONG FASTCALL BitmapFormat (WORD Bits, DWORD Compression); ULONG FASTCALL BitmapFormat(ULONG cBits, ULONG iCompression);
extern UCHAR gajBitsPerFormat[]; extern UCHAR gajBitsPerFormat[];
#define BitsPerFormat(Format) gajBitsPerFormat[Format] #define BitsPerFormat(Format) gajBitsPerFormat[Format]

View file

@ -161,60 +161,47 @@ NtGdiCreateBitmap(
IN OPTIONAL LPBYTE pUnsafeBits) IN OPTIONAL LPBYTE pUnsafeBits)
{ {
HBITMAP hbmp; HBITMAP hbmp;
ULONG cjWidthBytes, iFormat; ULONG cRealBpp, cjWidthBytes, iFormat;
ULONGLONG cjSize;
/* NOTE: Windows also doesn't store nr. of planes separately! */ /* Calculate bitmap format and real bits per pixel. */
cBitsPixel = BITMAP_GetRealBitsPixel(cBitsPixel * cPlanes); iFormat = BitmapFormat(cBitsPixel * cPlanes, BI_RGB);
cRealBpp = gajBitsPerFormat[iFormat];
/* Calculate bitmap format */ /* Calculate width and image size in bytes */
iFormat = BitmapFormat(cBitsPixel, BI_RGB); cjWidthBytes = WIDTH_BYTES_ALIGN16(nWidth, cRealBpp);
cjSize = cjWidthBytes * nHeight;
/* Check parameters */ /* Check parameters (possible overflow of cjWidthBytes!) */
if (iFormat == 0 || nWidth <= 0 || nHeight <= 0) if (iFormat == 0 || nWidth <= 0 || nWidth >= 0x8000000 || nHeight <= 0 ||
cBitsPixel > 32 || cPlanes > 32 || cjSize >= 0x100000000ULL)
{ {
DPRINT1("Width = %d, Height = %d BitsPixel = %d\n", DPRINT1("Invalid bitmap format! Width=%d, Height=%d, Bpp=%d, Planes=%d\n",
nWidth, nHeight, cBitsPixel); nWidth, nHeight, cBitsPixel, cPlanes);
EngSetLastError(ERROR_INVALID_PARAMETER); EngSetLastError(ERROR_INVALID_PARAMETER);
return NULL; return NULL;
} }
if(WIDTH_BYTES_ALIGN16(nWidth, cBitsPixel)*nHeight >= 0x8000000) /* Call internal function. */
{ hbmp = GreCreateBitmapEx(nWidth, nHeight, 0, iFormat, 0, 0, NULL, DDB_SURFACE);
/* I just can't get enough, I just can't get enough */
EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
return NULL;
}
/* Make sure that cjBits will not overflow */ if (pUnsafeBits && hbmp)
cjWidthBytes = WIDTH_BYTES_ALIGN16(nWidth, cBitsPixel);
if ((ULONGLONG)cjWidthBytes * nHeight >= 0x100000000ULL)
{ {
DPRINT1("Width = %d, Height = %d BitsPixel = %d\n", PSURFACE psurf = SURFACE_LockSurface(hbmp);
nWidth, nHeight, cBitsPixel);
EngSetLastError(ERROR_INVALID_PARAMETER);
return NULL;
}
/* cBitsPixel = cBitsPixel * cPlanes now! */
hbmp = GreCreateBitmap(nWidth, nHeight, 1, cBitsPixel, NULL);
if (pUnsafeBits)
{
PSURFACE psurf = SURFACE_LockSurface(hbmp);
_SEH2_TRY _SEH2_TRY
{ {
ProbeForRead(pUnsafeBits, cjWidthBytes * nHeight, 1); ProbeForRead(pUnsafeBits, cjSize, 1);
UnsafeSetBitmapBits(psurf, 0, pUnsafeBits); UnsafeSetBitmapBits(psurf, 0, pUnsafeBits);
} }
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{ {
SURFACE_UnlockSurface(psurf); SURFACE_UnlockSurface(psurf);
SURFACE_FreeSurfaceByHandle(hbmp); SURFACE_FreeSurfaceByHandle(hbmp);
_SEH2_YIELD(return NULL;) _SEH2_YIELD(return NULL;)
} }
_SEH2_END _SEH2_END
SURFACE_UnlockSurface(psurf); SURFACE_UnlockSurface(psurf);
} }
return hbmp; return hbmp;
@ -834,25 +821,6 @@ NtGdiSetPixel(
/* Internal Functions */ /* Internal Functions */
UINT FASTCALL
BITMAP_GetRealBitsPixel(UINT nBitsPixel)
{
if (nBitsPixel <= 1)
return 1;
if (nBitsPixel <= 4)
return 4;
if (nBitsPixel <= 8)
return 8;
if (nBitsPixel <= 16)
return 16;
if (nBitsPixel <= 24)
return 24;
if (nBitsPixel <= 32)
return 32;
return 0;
}
HBITMAP FASTCALL HBITMAP FASTCALL
BITMAP_CopyBitmap(HBITMAP hBitmap) BITMAP_CopyBitmap(HBITMAP hBitmap)
{ {