- 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

@ -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;
}

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)
@ -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;
@ -1069,8 +1072,6 @@ IntCreateDIBitmap(
if (bpp != 1) fColor = TRUE;
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);
@ -1086,25 +1087,6 @@ IntCreateDIBitmap(
}
else fColor = TRUE;
}
else if (data->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
{
RGBTRIPLE *rgb = ((BITMAPCOREINFO *)data)->bmciColors;
DWORD col = RGB(rgb->rgbtRed, rgb->rgbtGreen, rgb->rgbtBlue);
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;
}
}
// Now create the bitmap
if (fColor)
@ -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?