From ebe3986eb94fbc20f8b8601b5d1765bfb7a0a8dc Mon Sep 17 00:00:00 2001 From: James Tabor Date: Thu, 10 Mar 2011 13:45:09 +0000 Subject: [PATCH] [GDI32] - Protect SetDIBitsToDevice with seh and track it. This is for vbrun60spXX. Code fix ups and cleanup. svn path=/trunk/; revision=51009 --- reactos/dll/win32/gdi32/include/gdi32p.h | 1 - reactos/dll/win32/gdi32/objects/bitmap.c | 116 ++++++++++------------- reactos/dll/win32/gdi32/objects/utils.c | 2 +- 3 files changed, 53 insertions(+), 66 deletions(-) diff --git a/reactos/dll/win32/gdi32/include/gdi32p.h b/reactos/dll/win32/gdi32/include/gdi32p.h index 49673de0ce2..f4ef1d9342b 100644 --- a/reactos/dll/win32/gdi32/include/gdi32p.h +++ b/reactos/dll/win32/gdi32/include/gdi32p.h @@ -279,7 +279,6 @@ WINAPI GdiSetLastError( DWORD dwErrCode ); DWORD WINAPI GdiGetCodePage(HDC); -UINT FASTCALL DIB_BitmapBitsSize( CONST BITMAPINFO* ); int WINAPI diff --git a/reactos/dll/win32/gdi32/objects/bitmap.c b/reactos/dll/win32/gdi32/objects/bitmap.c index 024ac81f4cb..484c58a792f 100644 --- a/reactos/dll/win32/gdi32/objects/bitmap.c +++ b/reactos/dll/win32/gdi32/objects/bitmap.c @@ -3,6 +3,9 @@ #define NDEBUG #include +// From Yuan, ScanLineSize = (Width * bitcount + 31)/32 +#define WIDTH_BYTES_ALIGN32(cx, bpp) ((((cx) * (bpp) + 31) & ~31) >> 3) + /* * DIB_BitmapInfoSize * @@ -41,30 +44,6 @@ INT FASTCALL DIB_BitmapInfoSize(const BITMAPINFO * info, WORD coloruse) UINT FASTCALL DIB_BitmapMaxBitsSize( PBITMAPINFO Info, UINT ScanLines ) -{ - UINT MaxBits = 0; - - if (!Info) return 0; - - if (Info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER)) - { - PBITMAPCOREHEADER Core = (PBITMAPCOREHEADER)Info; - MaxBits = Core->bcBitCount * Core->bcPlanes * Core->bcWidth; - } - else /* assume BITMAPINFOHEADER */ - { - if ((Info->bmiHeader.biCompression) && (Info->bmiHeader.biCompression != BI_BITFIELDS)) - return Info->bmiHeader.biSizeImage; - // Planes are over looked by Yuan. I guess assumed always 1. - MaxBits = Info->bmiHeader.biBitCount * Info->bmiHeader.biPlanes * Info->bmiHeader.biWidth; - } - MaxBits = ((MaxBits + 31) & ~31 ) / 8; // From Yuan, ScanLineSize = (Width * bitcount + 31)/32 - return (MaxBits * ScanLines); // ret the full Size. -} - -UINT -FASTCALL -DIB_BitmapBitsSize( CONST BITMAPINFO* Info ) { UINT Ret; @@ -73,22 +52,22 @@ DIB_BitmapBitsSize( CONST BITMAPINFO* Info ) if ( Info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER)) { PBITMAPCOREHEADER Core = (PBITMAPCOREHEADER)Info; - Ret = Core->bcHeight * - ((Core->bcWidth * Core->bcPlanes * Core->bcBitCount + 31) & ~31 ) / 8; + Ret = WIDTH_BYTES_ALIGN32(Core->bcWidth * Core->bcPlanes, Core->bcBitCount) * ScanLines; } else /* assume BITMAPINFOHEADER */ { - if ((Info->bmiHeader.biCompression) && - (Info->bmiHeader.biCompression != BI_BITFIELDS)) - return Info->bmiHeader.biSizeImage; - // Make Height positive always.... - Ret = abs(Info->bmiHeader.biHeight) * - ((Info->bmiHeader.biWidth * Info->bmiHeader.biPlanes * Info->bmiHeader.biBitCount + 31) & ~31 ) / 8; + if (!(Info->bmiHeader.biCompression) || (Info->bmiHeader.biCompression == BI_BITFIELDS)) + { + Ret = WIDTH_BYTES_ALIGN32(Info->bmiHeader.biWidth * Info->bmiHeader.biPlanes, Info->bmiHeader.biBitCount) * ScanLines; + } + else + { + Ret = Info->bmiHeader.biSizeImage; + } } return Ret; } - /* * DIB_GetBitmapInfo is complete copy of wine cvs 2/9-2006 * from file dib.c from gdi32.dll or orginal version @@ -161,39 +140,27 @@ int WINAPI GdiGetBitmapBitsSize(BITMAPINFO *lpbmi) { - int retSize; + UINT Ret; + + if (!lpbmi) return 0; - if (lpbmi->bmiHeader.biSize == FIELD_OFFSET(BITMAPINFOHEADER, biPlanes)) + if ( lpbmi->bmiHeader.biSize == sizeof(BITMAPCOREHEADER)) { - /* 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) - & -32) / 8; + PBITMAPCOREHEADER Core = (PBITMAPCOREHEADER)lpbmi; + Ret = WIDTH_BYTES_ALIGN32(Core->bcWidth * Core->bcPlanes, Core->bcBitCount) * Core->bcHeight; } - else + else /* assume BITMAPINFOHEADER */ { - if ( (lpbmi->bmiHeader.biCompression == BI_BITFIELDS) || - (lpbmi->bmiHeader.biCompression == BI_RGB)) + if (!(lpbmi->bmiHeader.biCompression) || (lpbmi->bmiHeader.biCompression == BI_BITFIELDS)) { - if (lpbmi->bmiHeader.biHeight >=0 ) - { - /* Calc the bits Size and align it*/ - 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 * - lpbmi->bmiHeader.biPlanes * lpbmi->bmiHeader.biBitCount + 31) & -32) / 8; - } + Ret = WIDTH_BYTES_ALIGN32(lpbmi->bmiHeader.biWidth * lpbmi->bmiHeader.biPlanes, lpbmi->bmiHeader.biBitCount) * abs(lpbmi->bmiHeader.biHeight); } else { - retSize = lpbmi->bmiHeader.biSizeImage; + Ret = lpbmi->bmiHeader.biSizeImage; } } - return retSize; + return Ret; } /* @@ -316,7 +283,7 @@ StretchBlt( } /* - * @unimplemented + * @implemented */ HBITMAP WINAPI CreateBitmap(INT Width, @@ -325,7 +292,6 @@ CreateBitmap(INT Width, UINT BitsPixel, CONST VOID* pUnsafeBits) { - /* FIXME some part should be done in user mode */ if (Width && Height) { return NtGdiCreateBitmap(Width, Height, Planes, BitsPixel, (LPBYTE) pUnsafeBits); @@ -493,7 +459,7 @@ CreateDIBitmap( HDC hDC, { _SEH2_TRY { - cjBmpScanSize = DIB_BitmapBitsSize(Data); + cjBmpScanSize = GdiGetBitmapBitsSize((BITMAPINFO *)Data); CalculateColorTableSize(&Data->bmiHeader, &ColorUse, &InfoSize); InfoSize += Data->bmiHeader.biSize; } @@ -566,9 +532,9 @@ SetDIBits(HDC hDC, } } - hDCc = NtGdiGetDCforBitmap(hBitmap); + hDCc = NtGdiGetDCforBitmap(hBitmap); // hDC can be NULL, so, get it from the bitmap. SavehDC = hDCc; - if ( !hDCc ) + if ( !hDCc ) // No DC associated with bitmap, Clone or Create one. { nhDC = CreateCompatibleDC(hDC); if ( !nhDC ) return 0; @@ -648,6 +614,7 @@ SetDIBitsToDevice( UINT ConvertedInfoSize; INT LinesCopied = 0; UINT cjBmpScanSize = 0; + BOOL Hit = FALSE; PVOID pvSafeBits = (PVOID)Bits; if ( !ScanLines || !lpbmi || !Bits ) @@ -711,7 +678,26 @@ SetDIBitsToDevice( { pvSafeBits = RtlAllocateHeap(GetProcessHeap(), 0, cjBmpScanSize); if (pvSafeBits) - RtlCopyMemory( pvSafeBits, Bits, cjBmpScanSize); + { + _SEH2_TRY + { + RtlCopyMemory( pvSafeBits, Bits, cjBmpScanSize); + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + Hit = TRUE; + } + _SEH2_END + + if (Hit) + { + // We don't die, we continue on with a allocated safe pointer to kernel + // space..... + DPRINT1("SetDIBitsToDevice fail to read BitMapInfo: %x or Bits: %x & Size: %d\n",pConvertedInfo,Bits,cjBmpScanSize); + } + DPRINT("SetDIBitsToDevice Allocate Bits %d!!!\n", cjBmpScanSize); + } + } if (!GdiGetHandleUserData(hdc, GDI_OBJECT_TYPE_DC, (PVOID)&pDc_Attr)) @@ -720,7 +706,8 @@ SetDIBitsToDevice( return 0; } /* - if ( !pDc_Attr || + if ( !pDc_Attr || // DC is Public + ColorUse == DIB_PAL_COLORS || ((pConvertedInfo->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER)) && (pConvertedInfo->bmiHeader.biCompression == BI_JPEG || pConvertedInfo->bmiHeader.biCompression == BI_PNG )) )*/ @@ -833,7 +820,7 @@ StretchDIBits(HDC hdc, return 0; } - cjBmpScanSize = DIB_BitmapBitsSize((LPBITMAPINFO)pConvertedInfo); + cjBmpScanSize = GdiGetBitmapBitsSize((BITMAPINFO *)pConvertedInfo); if ( lpBits ) { @@ -867,6 +854,7 @@ StretchDIBits(HDC hdc, } /* if ( !pDc_Attr || + iUsage == DIB_PAL_COLORS || ((pConvertedInfo->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER)) && (pConvertedInfo->bmiHeader.biCompression == BI_JPEG || pConvertedInfo->bmiHeader.biCompression == BI_PNG )) )*/ diff --git a/reactos/dll/win32/gdi32/objects/utils.c b/reactos/dll/win32/gdi32/objects/utils.c index 734d5df54c6..7ed0d229d64 100644 --- a/reactos/dll/win32/gdi32/objects/utils.c +++ b/reactos/dll/win32/gdi32/objects/utils.c @@ -214,7 +214,7 @@ ConvertBitmapInfo( if (FollowedByData) { - DataSize = DIB_BitmapBitsSize((PBITMAPINFO)BitmapInfo ); + DataSize = GdiGetBitmapBitsSize((PBITMAPINFO)BitmapInfo ); } /* -- 2.17.1