- More BITMAPV5INFO fun
  - Probe max size we are asked for when converting to V5 Info
[USER32] [WIN32K]
  - CreateDIBitmap : Move safety handling to win32k, where it belongs. More code cleanness!

svn path=/branches/reactos-yarotows/; revision=47701
This commit is contained in:
Jérôme Gardou 2010-06-09 00:08:50 +00:00
parent 70f1514bfd
commit 974e9c0c41
4 changed files with 80 additions and 114 deletions

View file

@ -43,16 +43,16 @@ DIB_BitmapBitsSize( PBITMAPINFO Info )
if ( Info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
{
PBITMAPCOREHEADER Core = (PBITMAPCOREHEADER)Info;
Ret = Core->bcHeight *
Ret = Core->bcHeight *
((Core->bcWidth * Core->bcPlanes * Core->bcBitCount + 31) & ~31 ) / 8;
}
else /* assume BITMAPINFOHEADER */
{
if ((Info->bmiHeader.biCompression) &&
if ((Info->bmiHeader.biCompression) &&
(Info->bmiHeader.biCompression != BI_BITFIELDS))
return Info->bmiHeader.biSizeImage;
// Make Height positive always....
Ret = abs(Info->bmiHeader.biHeight) *
Ret = abs(Info->bmiHeader.biHeight) *
((Info->bmiHeader.biWidth * Info->bmiHeader.biPlanes * Info->bmiHeader.biBitCount + 31) & ~31 ) / 8;
}
return Ret;
@ -132,12 +132,12 @@ WINAPI
GdiGetBitmapBitsSize(BITMAPINFO *lpbmi)
{
int retSize;
if (lpbmi->bmiHeader.biSize == FIELD_OFFSET(BITMAPINFOHEADER, biPlanes))
{
/* Calc the bits Size and align it*/
retSize = HIWORD(lpbmi->bmiHeader.biWidth) * ((LOWORD(lpbmi->bmiHeader.biWidth) *
LOWORD(lpbmi->bmiHeader.biHeight) * HIWORD(lpbmi->bmiHeader.biHeight) + 31)
retSize = HIWORD(lpbmi->bmiHeader.biWidth) * ((LOWORD(lpbmi->bmiHeader.biWidth) *
LOWORD(lpbmi->bmiHeader.biHeight) * HIWORD(lpbmi->bmiHeader.biHeight) + 31)
& -32) / 8;
}
else
@ -148,13 +148,13 @@ GdiGetBitmapBitsSize(BITMAPINFO *lpbmi)
if (lpbmi->bmiHeader.biHeight >=0 )
{
/* Calc the bits Size and align it*/
retSize = lpbmi->bmiHeader.biHeight * ((lpbmi->bmiHeader.biWidth *
retSize = lpbmi->bmiHeader.biHeight * ((lpbmi->bmiHeader.biWidth *
lpbmi->bmiHeader.biPlanes * lpbmi->bmiHeader.biBitCount + 31) & -32) / 8;
}
else
{
/* Make height postiive if it negitve then calc the bits Size and align it*/
retSize = (-lpbmi->bmiHeader.biHeight) * ((lpbmi->bmiHeader.biWidth *
retSize = (-lpbmi->bmiHeader.biHeight) * ((lpbmi->bmiHeader.biWidth *
lpbmi->bmiHeader.biPlanes * lpbmi->bmiHeader.biBitCount + 31) & -32) / 8;
}
}
@ -189,7 +189,7 @@ CreateDIBSection(
{ // Verify header due to converted may == info.
if ( pConvertedInfo->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER) )
{
if ( pConvertedInfo->bmiHeader.biCompression == BI_JPEG ||
if ( pConvertedInfo->bmiHeader.biCompression == BI_JPEG ||
pConvertedInfo->bmiHeader.biCompression == BI_PNG )
{
SetLastError(ERROR_INVALID_PARAMETER);
@ -319,7 +319,7 @@ CreateBitmapIndirect(const BITMAP *pbm)
(!(pbm->bmWidthBytes & 1)) )
{
bitmap = CreateBitmap(pbm->bmWidth,
pbm->bmHeight,
pbm->bmPlanes,
@ -409,7 +409,7 @@ GetDIBits(
{
if ( lpbmi->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER) )
{
if ( lpbmi->bmiHeader.biCompression == BI_JPEG ||
if ( lpbmi->bmiHeader.biCompression == BI_JPEG ||
lpbmi->bmiHeader.biCompression == BI_PNG )
{
SetLastError(ERROR_INVALID_PARAMETER);
@ -461,78 +461,40 @@ CreateDIBitmap( HDC hDC,
LONG width, height, compr, dibsize;
WORD planes, bpp;
// PDC_ATTR pDc_Attr;
PBITMAPINFO pConvertedInfo;
UINT ConvertedInfoSize;
UINT cjBmpScanSize;
PVOID pvSafeBits = NULL;
HBITMAP hBmp;
if (!Header) return 0;
pConvertedInfo = ConvertBitmapInfo(Data, ColorUse,
&ConvertedInfoSize, FALSE);
if (DIB_GetBitmapInfo(Header, &width, &height, &planes, &bpp, &compr, &dibsize) == -1)
{
GdiSetLastError(ERROR_INVALID_PARAMETER);
return NULL;
}
if ( pConvertedInfo )
{
if ( pConvertedInfo->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER) )
{
if ( pConvertedInfo->bmiHeader.biCompression == BI_JPEG ||
pConvertedInfo->bmiHeader.biCompression == BI_PNG )
{
hBmp = NULL;
goto Exit;
}
}
}
// For Icm support.
// GdiGetHandleUserData(hdc, GDI_OBJECT_TYPE_DC, (PVOID)&pDc_Attr))
cjBmpScanSize = DIB_BitmapBitsSize((LPBITMAPINFO)pConvertedInfo);
DPRINT("pBMI %x, Size bpp %d, dibsize %d, Conv %d, BSS %d\n", pConvertedInfo,bpp,dibsize,ConvertedInfoSize,cjBmpScanSize);
cjBmpScanSize = DIB_BitmapBitsSize((LPBITMAPINFO)Header);
DPRINT("pBMI %x, Size bpp %d, dibsize %d, Conv %d, BSS %d\n", Data,bpp,dibsize,ConvertedInfoSize,cjBmpScanSize);
if ( !width || !height )
hBmp = GetStockObject(DEFAULT_BITMAP);
else
{
if ( Bits && Init == CBM_INIT )
{
pvSafeBits = RtlAllocateHeap(GetProcessHeap(), 0, cjBmpScanSize);
if (pvSafeBits == NULL)
{
hBmp = NULL;
goto Exit;
}
else
{
RtlCopyMemory( pvSafeBits, Bits, cjBmpScanSize);
}
}
hBmp = NtGdiCreateDIBitmapInternal(hDC,
width,
height,
Init,
(LPBYTE)pvSafeBits,
(PBITMAPINFO)pConvertedInfo,
(LPBYTE)Bits,
(LPBITMAPINFO)Data,
ColorUse,
ConvertedInfoSize,
cjBmpScanSize,
0,
0);
if ( Bits && Init == CBM_INIT )
RtlFreeHeap(RtlGetProcessHeap(), 0, pvSafeBits);
}
Exit:
if (Data != pConvertedInfo)
RtlFreeHeap(RtlGetProcessHeap(), 0, pConvertedInfo);
return hBmp;
}
@ -588,7 +550,7 @@ SetDIBits(HDC hDC,
if ( hOldBitmap )
{
if ( hDC )
if ( hDC )
hPal = SelectPalette(SavehDC, (HPALETTE)GetDCObject(hDC, GDI_OBJECT_TYPE_PALETTE), FALSE);
if ( lpbmi->bmiHeader.biSize < sizeof(BITMAPINFOHEADER))
@ -782,7 +744,7 @@ SetDIBitsToDevice(
/*
if ( !pDc_Attr ||
((pConvertedInfo->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER)) &&
(pConvertedInfo->bmiHeader.biCompression == BI_JPEG ||
(pConvertedInfo->bmiHeader.biCompression == BI_JPEG ||
pConvertedInfo->bmiHeader.biCompression == BI_PNG )) )*/
{
LinesCopied = NtGdiSetDIBitsToDeviceInternal( hdc,
@ -806,7 +768,7 @@ SetDIBitsToDevice(
RtlFreeHeap(RtlGetProcessHeap(), 0, pvSafeBits);
if (lpbmi != pConvertedInfo)
RtlFreeHeap(RtlGetProcessHeap(), 0, pConvertedInfo);
return LinesCopied;
}
@ -933,7 +895,7 @@ StretchDIBits(HDC hdc,
/*
if ( !pDc_Attr ||
((pConvertedInfo->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER)) &&
(pConvertedInfo->bmiHeader.biCompression == BI_JPEG ||
(pConvertedInfo->bmiHeader.biCompression == BI_JPEG ||
pConvertedInfo->bmiHeader.biCompression == BI_PNG )) )*/
{
LinesCopied = NtGdiStretchDIBitsInternal( hdc,

View file

@ -13,7 +13,7 @@ HBITMAP FASTCALL IntCreateBitmap(IN SIZEL Size, IN LONG Width, IN ULONG Format,
HBITMAP FASTCALL BITMAP_CopyBitmap (HBITMAP hBitmap);
UINT FASTCALL BITMAP_GetRealBitsPixel(UINT nBitsPixel);
INT FASTCALL BITMAP_GetWidthBytes (INT bmWidth, INT bpp);
NTSTATUS FASTCALL ProbeAndConvertToBitmapV5Info( OUT PBITMAPV5INFO pbmiDst, IN CONST BITMAPINFO* pbmiUnsafe, IN DWORD dwUse);
NTSTATUS FASTCALL ProbeAndConvertToBitmapV5Info( OUT PBITMAPV5INFO pbmiDst, IN CONST BITMAPINFO* pbmiUnsafe, IN DWORD dwUse, UINT MaxSize);
VOID FASTCALL GetBMIFromBitmapV5Info(IN PBITMAPV5INFO pbmiSrc, OUT PBITMAPINFO pbmiDst, IN DWORD dwUse);
HBITMAP

View file

@ -199,7 +199,8 @@ UserLoadImage(PCWSTR pwszName)
{
Status = ProbeAndConvertToBitmapV5Info(&bmiLocal,
pbmi,
DIB_RGB_COLORS);
DIB_RGB_COLORS,
0);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{

View file

@ -354,7 +354,8 @@ NtGdiSetDIBits(
_SEH2_TRY
{
Status = ProbeAndConvertToBitmapV5Info(&bmiLocal, bmi, ColorUse);
Status = ProbeAndConvertToBitmapV5Info(&bmiLocal, bmi, ColorUse, 0);
/* Don't check Bits and hope we won't die */
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
@ -427,7 +428,8 @@ NtGdiSetDIBitsToDeviceInternal(
_SEH2_TRY
{
Status = ProbeAndConvertToBitmapV5Info(&bmiLocal, bmi, ColorUse);
Status = ProbeAndConvertToBitmapV5Info(&bmiLocal, bmi, ColorUse, cjMaxInfo);
ProbeForRead(Bits, cjMaxBits, 1);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
@ -595,7 +597,7 @@ NtGdiGetDIBitsInternal(
_SEH2_TRY
{
Status = ProbeAndConvertToBitmapV5Info(&bmiLocal, Info, Usage);
Status = ProbeAndConvertToBitmapV5Info(&bmiLocal, Info, Usage, MaxInfo);
if (ChkBits) ProbeForWrite(ChkBits, MaxBits, 1);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
@ -842,7 +844,7 @@ NtGdiGetDIBitsInternal(
bmiLocal.bmiHeader.bV5BitCount) * DestSize.cy;
hDestBitmap = EngCreateBitmap(DestSize,
DIB_GetDIBWidthBytes(DestSize.cx,
DIB_GetDIBWidthBytes(DestSize.cx,
bmiLocal.bmiHeader.bV5BitCount),
BitmapFormat(bmiLocal.bmiHeader.bV5BitCount,
bmiLocal.bmiHeader.bV5Compression),
@ -942,7 +944,8 @@ NtGdiStretchDIBitsInternal(
HDC hdcMem;
HPALETTE hPal = NULL;
PDC pDC;
BOOL Hit = FALSE;
NTSTATUS Status;
BITMAPV5INFO bmiLocal ;
if (!Bits || !BitsInfo)
{
@ -952,16 +955,16 @@ NtGdiStretchDIBitsInternal(
_SEH2_TRY
{
ProbeForRead(BitsInfo, cjMaxInfo, 1);
Status = ProbeAndConvertToBitmapV5Info(&bmiLocal, BitsInfo, Usage, cjMaxInfo);
ProbeForRead(Bits, cjMaxBits, 1);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
Hit = TRUE;
Status = _SEH2_GetExceptionCode();
}
_SEH2_END
if (Hit)
if (!NT_SUCCESS(Status))
{
DPRINT1("NtGdiStretchDIBitsInternal fail to read BitMapInfo: %x or Bits: %x\n",BitsInfo,Bits);
return 0;
@ -975,8 +978,8 @@ NtGdiStretchDIBitsInternal(
}
hBitmap = NtGdiCreateCompatibleBitmap(hDC,
abs(BitsInfo->bmiHeader.biWidth),
abs(BitsInfo->bmiHeader.biHeight));
abs(bmiLocal.bmiHeader.bV5Width),
abs(bmiLocal.bmiHeader.bV5Height));
if (hBitmap == NULL)
{
DPRINT1("NtGdiCreateCompatibleBitmap fail create bitmap\n");
@ -995,15 +998,15 @@ NtGdiStretchDIBitsInternal(
hPal = GdiSelectPalette(hdcMem, hPal, FALSE);
}
if (BitsInfo->bmiHeader.biCompression == BI_RLE4 ||
BitsInfo->bmiHeader.biCompression == BI_RLE8)
if (bmiLocal.bmiHeader.bV5Compression == BI_RLE4 ||
bmiLocal.bmiHeader.bV5Compression == BI_RLE8)
{
/* copy existing bitmap from destination dc */
if (SrcWidth == DestWidth && SrcHeight == DestHeight)
NtGdiBitBlt(hdcMem, XSrc, abs(BitsInfo->bmiHeader.biHeight) - SrcHeight - YSrc,
NtGdiBitBlt(hdcMem, XSrc, abs(bmiLocal.bmiHeader.bV5Height) - SrcHeight - YSrc,
SrcWidth, SrcHeight, hDC, XDest, YDest, ROP, 0, 0);
else
NtGdiStretchBlt(hdcMem, XSrc, abs(BitsInfo->bmiHeader.biHeight) - SrcHeight - YSrc,
NtGdiStretchBlt(hdcMem, XSrc, abs(bmiLocal.bmiHeader.bV5Height) - SrcHeight - YSrc,
SrcWidth, SrcHeight, hDC, XDest, YDest, DestWidth, DestHeight,
ROP, 0);
}
@ -1015,8 +1018,8 @@ NtGdiStretchDIBitsInternal(
* if it negitve we getting to many scanline for scanline is UINT not
* a INT, so we need make the negtive value to positve and that make the
* count correct for negtive bitmap, TODO : we need testcase for this api */
IntSetDIBits(pDC, hBitmap, 0, abs(BitsInfo->bmiHeader.biHeight), Bits,
BitsInfo, Usage);
IntSetDIBits(pDC, hBitmap, 0, abs(bmiLocal.bmiHeader.bV5Height), Bits,
(PBITMAPINFO)&bmiLocal, Usage);
DC_UnlockDc(pDC);
}
@ -1026,11 +1029,11 @@ NtGdiStretchDIBitsInternal(
left (negative biHeight) */
if (SrcWidth == DestWidth && SrcHeight == DestHeight)
NtGdiBitBlt(hDC, XDest, YDest, DestWidth, DestHeight,
hdcMem, XSrc, abs(BitsInfo->bmiHeader.biHeight) - SrcHeight - YSrc,
hdcMem, XSrc, abs(bmiLocal.bmiHeader.bV5Height) - SrcHeight - YSrc,
ROP, 0, 0);
else
NtGdiStretchBlt(hDC, XDest, YDest, DestWidth, DestHeight,
hdcMem, XSrc, abs(BitsInfo->bmiHeader.biHeight) - SrcHeight - YSrc,
hdcMem, XSrc, abs(bmiLocal.bmiHeader.bV5Height) - SrcHeight - YSrc,
SrcWidth, SrcHeight, ROP, 0);
/* cleanup */
@ -1057,7 +1060,7 @@ IntCreateDIBitmap(
UINT bpp,
DWORD init,
LPBYTE bits,
PBITMAPINFO data,
PBITMAPV5INFO data,
DWORD coloruse)
{
HBITMAP handle;
@ -1070,40 +1073,19 @@ IntCreateDIBitmap(
else if ((coloruse != DIB_RGB_COLORS) || (init != CBM_INIT) || !data) fColor = FALSE;
else
{
if (data->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
{
const RGBQUAD *rgb = data->bmiColors;
DWORD col = RGB(rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue);
const RGBQUAD *rgb = data->bmiColors;
DWORD col = RGB(rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue);
// Check if the first color of the colormap is black
if ((col == RGB(0, 0, 0)))
{
rgb++;
col = RGB(rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue);
// If the second color is white, create a monochrome bitmap
fColor = (col != RGB(0xff,0xff,0xff));
}
else fColor = TRUE;
}
else if (data->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
// Check if the first color of the colormap is black
if ((col == RGB(0, 0, 0)))
{
RGBTRIPLE *rgb = ((BITMAPCOREINFO *)data)->bmciColors;
DWORD col = RGB(rgb->rgbtRed, rgb->rgbtGreen, rgb->rgbtBlue);
rgb++;
col = RGB(rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue);
if ((col == RGB(0,0,0)))
{
rgb++;
col = RGB(rgb->rgbtRed, rgb->rgbtGreen, rgb->rgbtBlue);
fColor = (col != RGB(0xff,0xff,0xff));
}
else fColor = TRUE;
}
else
{
DPRINT("(%ld): wrong size for data\n", data->bmiHeader.biSize);
return 0;
// If the second color is white, create a monochrome bitmap
fColor = (col != RGB(0xff,0xff,0xff));
}
else fColor = TRUE;
}
// Now create the bitmap
@ -1125,7 +1107,7 @@ IntCreateDIBitmap(
if (NULL != handle && CBM_INIT == init)
{
IntSetDIBits(Dc, handle, 0, height, bits, data, coloruse);
IntSetDIBits(Dc, handle, 0, height, bits, (BITMAPINFO*)data, coloruse);
}
return handle;
@ -1151,6 +1133,25 @@ NtGdiCreateDIBitmapInternal(
PDC Dc;
HBITMAP Bmp;
UINT bpp;
BITMAPV5INFO bmiLocal ;
NTSTATUS Status = STATUS_SUCCESS;
_SEH2_TRY
{
if(pbmi) Status = ProbeAndConvertToBitmapV5Info(&bmiLocal, pbmi, iUsage, cjMaxInitInfo);
if(pjInit && (fInit == CBM_INIT)) ProbeForRead(pjInit, cjMaxBits, 1);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
Status = _SEH2_GetExceptionCode();
}
_SEH2_END
if(!NT_SUCCESS(Status))
{
SetLastNtError(Status);
return NULL;
}
if (!hDc) // CreateBitmap
{ // Should use System Bitmap DC hSystemBM, with CreateCompatibleDC for this.
@ -1169,7 +1170,7 @@ NtGdiCreateDIBitmapInternal(
return NULL;
}
bpp = 1;
Bmp = IntCreateDIBitmap(Dc, cx, cy, bpp, fInit, pjInit, pbmi, iUsage);
Bmp = IntCreateDIBitmap(Dc, cx, cy, bpp, fInit, pjInit, pbmi ? &bmiLocal : NULL, iUsage);
DC_UnlockDc(Dc);
NtGdiDeleteObjectApp(hDc);
@ -1187,7 +1188,7 @@ NtGdiCreateDIBitmapInternal(
should match that of the hdc and not that supplied in bmih.
*/
if (pbmi)
bpp = pbmi->bmiHeader.biBitCount;
bpp = bmiLocal.bmiHeader.bV5BitCount;
else
{
if (Dc->dctype != DC_TYPE_MEMORY)
@ -1211,7 +1212,7 @@ NtGdiCreateDIBitmapInternal(
}
}
}
Bmp = IntCreateDIBitmap(Dc, cx, cy, bpp, fInit, pjInit, pbmi, iUsage);
Bmp = IntCreateDIBitmap(Dc, cx, cy, bpp, fInit, pjInit, pbmi ? &bmiLocal : NULL, iUsage);
DC_UnlockDc(Dc);
}
return Bmp;
@ -1760,7 +1761,8 @@ FASTCALL
ProbeAndConvertToBitmapV5Info(
OUT PBITMAPV5INFO pbmiDst,
IN CONST BITMAPINFO* pbmiUnsafe,
IN DWORD dwColorUse)
IN DWORD dwColorUse,
IN UINT MaxSize)
{
DWORD dwSize;
ULONG ulWidthBytes;
@ -1769,7 +1771,8 @@ ProbeAndConvertToBitmapV5Info(
/* Get the size and probe */
ProbeForRead(&pbmiUnsafe->bmiHeader.biSize, sizeof(DWORD), 1);
dwSize = pbmiUnsafe->bmiHeader.biSize;
ProbeForRead(pbmiUnsafe, dwSize, 1);
/* At least dwSize bytes must be valids */
ProbeForRead(pbmiUnsafe, max(dwSize, MaxSize), 1);
/* Check the size */
// FIXME: are intermediate sizes allowed? As what are they interpreted?