From fa0375352fcd3a9d2be6148d2defee89df9cf615 Mon Sep 17 00:00:00 2001 From: James Tabor Date: Tue, 18 Nov 2008 05:36:19 +0000 Subject: [PATCH] - Fixes bug 3864. While I was at it I fixed most of the gdi max bit max info sizes too. - Added notes for the SEH abuse in win32k dibobj.c. - Tested WinMerge 2.10.2, AbiWord 2.4.1, Firefox 1.5.0.3 and wine gdi32 bitmap cross test. - When testing with gdi cross test in 24 and 32 bit display mode, we have a pixel conversion mismatch. Please fix it! svn path=/trunk/; revision=37436 --- reactos/dll/win32/gdi32/include/gdi32p.h | 1 + reactos/dll/win32/gdi32/misc/stubs.c | 22 - reactos/dll/win32/gdi32/objects/bitmap.c | 537 +++++++++++++++--- reactos/dll/win32/gdi32/objects/utils.c | 27 +- reactos/subsystems/win32/win32k/include/dc.h | 1 + .../subsystems/win32/win32k/objects/dibobj.c | 42 +- 6 files changed, 504 insertions(+), 126 deletions(-) diff --git a/reactos/dll/win32/gdi32/include/gdi32p.h b/reactos/dll/win32/gdi32/include/gdi32p.h index 43020095184..09c6af19ca6 100644 --- a/reactos/dll/win32/gdi32/include/gdi32p.h +++ b/reactos/dll/win32/gdi32/include/gdi32p.h @@ -231,6 +231,7 @@ STDCALL GdiSetLastError( DWORD dwErrCode ); DWORD STDCALL GdiGetCodePage(HDC); +UINT FASTCALL DIB_BitmapBitsSize( PBITMAPINFO ); /* EOF */ diff --git a/reactos/dll/win32/gdi32/misc/stubs.c b/reactos/dll/win32/gdi32/misc/stubs.c index cff3e0d665b..98531091fa1 100644 --- a/reactos/dll/win32/gdi32/misc/stubs.c +++ b/reactos/dll/win32/gdi32/misc/stubs.c @@ -1786,28 +1786,6 @@ CombineRgn(HRGN hDest, return NtGdiCombineRgn(hDest, hSrc1, hSrc2, CombineMode); } -/* - * @unimplemented - */ -HBITMAP STDCALL -CreateBitmap(INT Width, - INT Height, - UINT Planes, - UINT BitsPixel, - PCVOID pUnsafeBits) -{ - /* FIXME some part should be done in user mode */ - if (Width && Height) - { - return NtGdiCreateBitmap(Width, Height, Planes, BitsPixel, (LPBYTE) pUnsafeBits); - } - else - { - /* Return 1x1 bitmap */ - return GetStockObject(DEFAULT_BITMAP); - } -} - /* * @unimplemented */ diff --git a/reactos/dll/win32/gdi32/objects/bitmap.c b/reactos/dll/win32/gdi32/objects/bitmap.c index 5e38b05ef13..6e3a8c11b82 100644 --- a/reactos/dll/win32/gdi32/objects/bitmap.c +++ b/reactos/dll/win32/gdi32/objects/bitmap.c @@ -6,7 +6,7 @@ /* * Return the full scan size for a bitmap. * - * Based on Wine, Utils.c and Windows Graphics Prog pg 595 + * Based on Wine, Utils.c and Windows Graphics Prog pg 595, SDK amvideo.h. */ UINT FASTCALL @@ -14,6 +14,8 @@ DIB_BitmapMaxBitsSize( PBITMAPINFO Info, UINT ScanLines ) { UINT MaxBits = 0; + if (!Info) return 0; + if (Info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER)) { PBITMAPCOREHEADER Core = (PBITMAPCOREHEADER)Info; @@ -30,6 +32,33 @@ DIB_BitmapMaxBitsSize( PBITMAPINFO Info, UINT ScanLines ) return (MaxBits * ScanLines); // ret the full Size. } +UINT +FASTCALL +DIB_BitmapBitsSize( PBITMAPINFO Info ) +{ + UINT Ret; + + if (!Info) return 0; + + if ( Info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER)) + { + PBITMAPCOREHEADER Core = (PBITMAPCOREHEADER)Info; + Ret = Core->bcHeight * + ((Core->bcWidth * Core->bcPlanes * Core->bcBitCount + 31) & ~31 ) / 8; + } + 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; + } + return Ret; +} + + /* * DIB_GetBitmapInfo is complete copy of wine cvs 2/9-2006 * from file dib.c from gdi32.dll or orginal version @@ -111,16 +140,42 @@ CreateDIBSection( PBITMAPINFO pConvertedInfo; UINT ConvertedInfoSize; HBITMAP hBitmap = NULL; + PVOID bmBits = NULL; pConvertedInfo = ConvertBitmapInfo(BitmapInfo, Usage, &ConvertedInfoSize, FALSE); if (pConvertedInfo) - { - hBitmap = NtGdiCreateDIBSection(hDC, hSection, dwOffset, pConvertedInfo, Usage, 0, 0, 0, Bits); + { // Verify header due to converted may == info. + if ( pConvertedInfo->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER) ) + { + if ( pConvertedInfo->bmiHeader.biCompression == BI_JPEG || + pConvertedInfo->bmiHeader.biCompression == BI_PNG ) + { + SetLastError(ERROR_INVALID_PARAMETER); + return NULL; + } + } + bmBits = Bits; + hBitmap = NtGdiCreateDIBSection( hDC, + hSection, + dwOffset, + pConvertedInfo, + Usage, + 0, + 0, + 0, + &bmBits); if (BitmapInfo != pConvertedInfo) RtlFreeHeap(RtlGetProcessHeap(), 0, pConvertedInfo); + + if (!hBitmap) + { + bmBits = NULL; + } } + if (Bits) *Bits = bmBits; + return hBitmap; } @@ -190,6 +245,28 @@ StretchBlt( nHeightDest, hdcSrc, nXOriginSrc, nYOriginSrc, dwRop, 0, 0); } +/* + * @unimplemented + */ +HBITMAP STDCALL +CreateBitmap(INT Width, + INT Height, + UINT Planes, + UINT BitsPixel, + PCVOID pUnsafeBits) +{ + /* FIXME some part should be done in user mode */ + if (Width && Height) + { + return NtGdiCreateBitmap(Width, Height, Planes, BitsPixel, (LPBYTE) pUnsafeBits); + } + else + { + /* Return 1x1 bitmap */ + return GetStockObject(DEFAULT_BITMAP); + } +} + /* * @implemented */ @@ -234,12 +311,38 @@ CreateCompatibleBitmap( INT Width, INT Height) { - /* FIXME some part shall be done in user mode */ - return NtGdiCreateCompatibleBitmap(hDC, Width, Height); + PDC_ATTR pDc_Attr; + HBITMAP hBmp = NULL; + DIBSECTION dibs; + + if (!GdiGetHandleUserData(hDC, GDI_OBJECT_TYPE_DC, (PVOID)&pDc_Attr)) + return NULL; + + if ( !Width || !Height ) + return GetStockObject(DEFAULT_BITMAP); + + if (!(pDc_Attr->ulDirty_ & DC_DIBSECTION)) + { + return NtGdiCreateCompatibleBitmap(hDC, Width, Height); + } + + hBmp = NtGdiGetDCObject(hDC, GDI_OBJECT_TYPE_BITMAP); + + if ( GetObjectA(hBmp, sizeof(DIBSECTION), &dibs) != sizeof(DIBSECTION) ) + return NULL; + + if ( dibs.dsBm.bmBitsPixel <= 8 ) + GetDIBColorTable(hDC, 0, 256, (RGBQUAD *)&dibs.dsBitfields); + + dibs.dsBmih.biWidth = Width; + dibs.dsBmih.biHeight = Height; + + return CreateDIBSection(hDC, (CONST BITMAPINFO *)&dibs.dsBmih, 0, NULL, NULL, 0); } + INT STDCALL GetDIBits( @@ -251,34 +354,50 @@ GetDIBits( LPBITMAPINFO lpbmi, UINT uUsage) { - INT ret = 0; + INT Ret = 0; + UINT cjBmpScanSize; + PVOID pvSafeBits = lpvBits; - if (hDC == NULL || !GdiIsHandleValid((HGDIOBJ)hDC)) - { - GdiSetLastError(ERROR_INVALID_PARAMETER); - } - else if (lpbmi == NULL) - { - // XP doesn't run this check and results in a - // crash in DIB_BitmapMaxBitsSize, we'll be more forgiving - GdiSetLastError(ERROR_INVALID_PARAMETER); - } - else - { - UINT cjBmpScanSize = DIB_BitmapMaxBitsSize(lpbmi, cScanLines); + if (!hDC || !GdiIsHandleValid((HGDIOBJ)hDC)) + { + GdiSetLastError(ERROR_INVALID_PARAMETER); + return Ret; + } - ret = NtGdiGetDIBitsInternal(hDC, - hbmp, - uStartScan, - cScanLines, - lpvBits, - lpbmi, - uUsage, - cjBmpScanSize, - 0); - } + cjBmpScanSize = DIB_BitmapMaxBitsSize(lpbmi, cScanLines); - return ret; + if ( lpvBits ) + { + if ( lpbmi ) + { + if ( lpbmi->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER) ) + { + if ( lpbmi->bmiHeader.biCompression == BI_JPEG || + lpbmi->bmiHeader.biCompression == BI_PNG ) + { + SetLastError(ERROR_INVALID_PARAMETER); + return Ret; + } + } + } + pvSafeBits = RtlAllocateHeap(GetProcessHeap(), 0, cjBmpScanSize); + } + + Ret = NtGdiGetDIBitsInternal(hDC, + hbmp, + uStartScan, + cScanLines, + pvSafeBits, + lpbmi, + uUsage, + cjBmpScanSize, + 0); + if ( lpvBits ) + { + RtlCopyMemory( lpvBits, pvSafeBits, cjBmpScanSize); + RtlFreeHeap(RtlGetProcessHeap(), 0, pvSafeBits); + } + return Ret; } /* @@ -293,26 +412,73 @@ CreateDIBitmap( HDC hDC, const BITMAPINFO *Data, UINT ColorUse) { - LONG width, height, compr, dibsize; - WORD planes, bpp; + LONG width, height, compr, dibsize; + WORD planes, bpp; +// PDC_ATTR pDc_Attr; + PBITMAPINFO pConvertedInfo; + UINT ConvertedInfoSize; + UINT cjBmpScanSize; + PVOID pvSafeBits = NULL; + HBITMAP hBmp; - if (DIB_GetBitmapInfo(Header, &width, &height, &planes, &bpp, &compr, &dibsize) == -1) - { - GdiSetLastError(ERROR_INVALID_PARAMETER); - return NULL; - } + pConvertedInfo = ConvertBitmapInfo(Data, ColorUse, + &ConvertedInfoSize, FALSE); - return NtGdiCreateDIBitmapInternal(hDC, - width, - height, - Init, - (LPBYTE)Bits, - (PBITMAPINFO)Data, - ColorUse, - bpp, - dibsize, - 0, - 0); + 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); + + if ( !width || !height ) + hBmp = GetStockObject(DEFAULT_BITMAP); + else + { + if ( Bits ) + { + pvSafeBits = RtlAllocateHeap(GetProcessHeap(), 0, cjBmpScanSize); + if ( pvSafeBits ) + RtlCopyMemory( pvSafeBits, Bits, cjBmpScanSize); + } + + hBmp = NtGdiCreateDIBitmapInternal(hDC, + width, + height, + Init, + (LPBYTE)pvSafeBits, + (PBITMAPINFO)pConvertedInfo, + ColorUse, + ConvertedInfoSize, + cjBmpScanSize, + 0, + 0); + + if ( Bits ) + RtlFreeHeap(RtlGetProcessHeap(), 0, pvSafeBits); + } +Exit: + if (Data != pConvertedInfo) + RtlFreeHeap(RtlGetProcessHeap(), 0, pConvertedInfo); + return hBmp; } #if 0 // FIXME!!! This is a victim of the Win32k Initialization BUG!!!!! @@ -419,7 +585,25 @@ SetDIBits(HDC hdc, CONST BITMAPINFO *lpbmi, UINT fuColorUse) { - return NtGdiSetDIBits(hdc, hbmp, uStartScan, cScanLines, lpvBits, lpbmi, fuColorUse); + INT LinesCopied = 0; + +// This needs to be almost the sames as SetDIBitsToDevice + + if ( !cScanLines || !lpbmi || !lpvBits || (GDI_HANDLE_GET_TYPE(hbmp) != GDI_OBJECT_TYPE_BITMAP)) + return 0; + + if ( fuColorUse && fuColorUse != DIB_PAL_COLORS && fuColorUse != DIB_PAL_COLORS+1 ) + return 0; + + LinesCopied = NtGdiSetDIBits( hdc, + hbmp, + uStartScan, + cScanLines, + lpvBits, + lpbmi, + fuColorUse); + + return LinesCopied; } /* @@ -429,7 +613,7 @@ SetDIBits(HDC hdc, INT STDCALL SetDIBitsToDevice( - HDC hDC, + HDC hdc, int XDest, int YDest, DWORD Width, @@ -442,22 +626,111 @@ SetDIBitsToDevice( CONST BITMAPINFO *lpbmi, UINT ColorUse) { - return NtGdiSetDIBitsToDeviceInternal(hDC, - XDest, - YDest, - Width, - Height, - XSrc, - YSrc, - StartScan, - ScanLines, - (LPBYTE)Bits, - (LPBITMAPINFO)lpbmi, - ColorUse, - lpbmi->bmiHeader.biSizeImage, - lpbmi->bmiHeader.biSize, - TRUE, - NULL); + PDC_ATTR pDc_Attr; + PBITMAPINFO pConvertedInfo; + UINT ConvertedInfoSize; + INT LinesCopied = 0; + UINT cjBmpScanSize = 0; + PVOID pvSafeBits = (PVOID)Bits; + + if ( !ScanLines || !lpbmi || !Bits ) + return 0; + + if ( ColorUse && ColorUse != DIB_PAL_COLORS && ColorUse != DIB_PAL_COLORS+1 ) + return 0; + + pConvertedInfo = ConvertBitmapInfo(lpbmi, ColorUse, + &ConvertedInfoSize, FALSE); + if (!pConvertedInfo) + return 0; + +#if 0 +// Handle something other than a normal dc object. + if (GDI_HANDLE_GET_TYPE(hdc) != GDI_OBJECT_TYPE_DC) + { + if (GDI_HANDLE_GET_TYPE(hdc) == GDI_OBJECT_TYPE_METADC) + return MFDRV_SetDIBitsToDevice( hdc, + XDest, + YDest, + Width, + Height, + XSrc, + YSrc, + StartScan, + ScanLines, + Bits, + lpbmi, + ColorUse); + else + { + PLDC pLDC = GdiGetLDC(hdc); + if ( !pLDC ) + { + SetLastError(ERROR_INVALID_HANDLE); + return 0; + } + if (pLDC->iType == LDC_EMFLDC) + { + return EMFDRV_SetDIBitsToDevice(hdc, + XDest, + YDest, + Width, + Height, + XSrc, + YSrc, + StartScan, + ScanLines, + Bits, + lpbmi, + ColorUse); + } + return 0; + } + } +#endif + cjBmpScanSize = DIB_BitmapMaxBitsSize((LPBITMAPINFO)lpbmi, ScanLines); + + if ( Bits ) + { + pvSafeBits = RtlAllocateHeap(GetProcessHeap(), 0, cjBmpScanSize); + if (pvSafeBits) + RtlCopyMemory( pvSafeBits, Bits, cjBmpScanSize); + } + + if (!GdiGetHandleUserData(hdc, GDI_OBJECT_TYPE_DC, (PVOID)&pDc_Attr)) + { + SetLastError(ERROR_INVALID_PARAMETER); + return 0; + } +/* + if ( !pDc_Attr || + ((pConvertedInfo->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER)) && + (pConvertedInfo->bmiHeader.biCompression == BI_JPEG || + pConvertedInfo->bmiHeader.biCompression == BI_PNG )) )*/ + { + LinesCopied = NtGdiSetDIBitsToDeviceInternal( hdc, + XDest, + YDest, + Width, + Height, + XSrc, + YSrc, + StartScan, + ScanLines, + (LPBYTE)pvSafeBits, + (LPBITMAPINFO)pConvertedInfo, + ColorUse, + cjBmpScanSize, + ConvertedInfoSize, + TRUE, + NULL); + } + if ( Bits ) + RtlFreeHeap(RtlGetProcessHeap(), 0, pvSafeBits); + if (lpbmi != pConvertedInfo) + RtlFreeHeap(RtlGetProcessHeap(), 0, pConvertedInfo); + + return LinesCopied; } @@ -481,9 +754,133 @@ StretchDIBits(HDC hdc, DWORD dwRop) { - DPRINT("StretchDIBits %x : %x\n", lpBits, lpBitsInfo); - /* FIXME share memory */ - return NtGdiStretchDIBitsInternal(hdc, XDest, YDest, nDestWidth, nDestHeight, XSrc, YSrc, - nSrcWidth, nSrcHeight, (LPBYTE)lpBits, (LPBITMAPINFO)lpBitsInfo, (DWORD)iUsage, dwRop, 0, 0, NULL); + PDC_ATTR pDc_Attr; + PBITMAPINFO pConvertedInfo = NULL; + UINT ConvertedInfoSize = 0; + INT LinesCopied = 0; + UINT cjBmpScanSize = 0; + PVOID pvSafeBits = NULL; + BOOL Hit = FALSE; + + DPRINT("StretchDIBits %x : %x : %d\n", lpBits, lpBitsInfo, iUsage); +#if 0 +// Handle something other than a normal dc object. + if (GDI_HANDLE_GET_TYPE(hdc) != GDI_OBJECT_TYPE_DC) + { + if (GDI_HANDLE_GET_TYPE(hdc) == GDI_OBJECT_TYPE_METADC) + return MFDRV_StretchBlt( hdc, + XDest, + YDest, + nDestWidth, + nDestHeight, + XSrc, + YSrc, + nSrcWidth, + nSrcHeight, + lpBits, + lpBitsInfo, + iUsage, + dwRop); + else + { + PLDC pLDC = GdiGetLDC(hdc); + if ( !pLDC ) + { + SetLastError(ERROR_INVALID_HANDLE); + return 0; + } + if (pLDC->iType == LDC_EMFLDC) + { + return EMFDRV_StretchBlt(hdc, + XDest, + YDest, + nDestWidth, + nDestHeight, + XSrc, + YSrc, + nSrcWidth, + nSrcHeight, + lpBits, + lpBitsInfo, + iUsage, + dwRop); + } + return 0; + } + } +#endif + if ( iUsage ) // Save time, we only look at non RGB. + { + pConvertedInfo = ConvertBitmapInfo(lpBitsInfo, iUsage, + &ConvertedInfoSize, FALSE); + if (!pConvertedInfo) + { + return 0; + } + } + else + pConvertedInfo = (PBITMAPINFO)lpBitsInfo; + + cjBmpScanSize = DIB_BitmapBitsSize((LPBITMAPINFO)pConvertedInfo); + + if ( lpBits ) + { + pvSafeBits = RtlAllocateHeap(GetProcessHeap(), 0, cjBmpScanSize); + if (pvSafeBits) + { + _SEH_TRY + { + RtlCopyMemory( pvSafeBits, lpBits, cjBmpScanSize ); + } + _SEH_HANDLE + { + Hit = TRUE; + } + _SEH_END + + if (Hit) + { + // We don't die, we continue on with a allocated safe pointer to kernel + // space..... + DPRINT1("StretchDIBits fail to read BitMapInfo: %x or Bits: %x & Size: %d\n",pConvertedInfo,lpBits,cjBmpScanSize); + } + DPRINT("StretchDIBits Allocate Bits %d!!!\n", cjBmpScanSize); + } + } + + if (!GdiGetHandleUserData(hdc, GDI_OBJECT_TYPE_DC, (PVOID)&pDc_Attr)) + { + SetLastError(ERROR_INVALID_PARAMETER); + return 0; + } +/* + if ( !pDc_Attr || + ((pConvertedInfo->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER)) && + (pConvertedInfo->bmiHeader.biCompression == BI_JPEG || + pConvertedInfo->bmiHeader.biCompression == BI_PNG )) )*/ + { + LinesCopied = NtGdiStretchDIBitsInternal( hdc, + XDest, + YDest, + nDestWidth, + nDestHeight, + XSrc, + YSrc, + nSrcWidth, + nSrcHeight, + pvSafeBits, + pConvertedInfo, + (DWORD)iUsage, + dwRop, + ConvertedInfoSize, + cjBmpScanSize, + NULL); + } + if ( pvSafeBits ) + RtlFreeHeap(RtlGetProcessHeap(), 0, pvSafeBits); + if (lpBitsInfo != pConvertedInfo) + RtlFreeHeap(RtlGetProcessHeap(), 0, pConvertedInfo); + + return LinesCopied; } diff --git a/reactos/dll/win32/gdi32/objects/utils.c b/reactos/dll/win32/gdi32/objects/utils.c index ee0ab1bac26..ae746d33ab1 100644 --- a/reactos/dll/win32/gdi32/objects/utils.c +++ b/reactos/dll/win32/gdi32/objects/utils.c @@ -214,32 +214,7 @@ ConvertBitmapInfo( if (FollowedByData) { - if (BitmapInfo->bmiHeader.biSize == sizeof(BITMAPCOREHEADER)) - { - DataSize = - CoreBitmapInfo->bmciHeader.bcHeight * - CoreBitmapInfo->bmciHeader.bcWidth * - CoreBitmapInfo->bmciHeader.bcBitCount; - DataSize = ((DataSize + 31) & ~31) / 8; - DataSize *= CoreBitmapInfo->bmciHeader.bcPlanes; - } - else - { - if (BitmapInfo->bmiHeader.biCompression == BI_RGB || - BitmapInfo->bmiHeader.biCompression == BI_BITFIELDS) - { - DataSize = - abs(BitmapInfo->bmiHeader.biHeight) * - BitmapInfo->bmiHeader.biWidth * - BitmapInfo->bmiHeader.biBitCount; - DataSize = ((DataSize + 31) & ~31) / 8; - DataSize *= BitmapInfo->bmiHeader.biPlanes; - } - else - { - DataSize = BitmapInfo->bmiHeader.biSizeImage; - } - } + DataSize = DIB_BitmapBitsSize((PBITMAPINFO)BitmapInfo ); } /* diff --git a/reactos/subsystems/win32/win32k/include/dc.h b/reactos/subsystems/win32/win32k/include/dc.h index cec7c45730e..7fb80a91e26 100644 --- a/reactos/subsystems/win32/win32k/include/dc.h +++ b/reactos/subsystems/win32/win32k/include/dc.h @@ -270,6 +270,7 @@ BOOL FASTCALL IntGdiCleanDC(HDC hDC); VOID FASTCALL IntvGetDeviceCaps(PGDIDEVICE, PDEVCAPS); HPEN FASTCALL IntGdiSelectPen(PDC,HPEN); HBRUSH FASTCALL IntGdiSelectBrush(PDC,HBRUSH); +INT FASTCALL IntGdiGetDeviceCaps(PDC,INT); extern PGDIDEVICE pPrimarySurface; diff --git a/reactos/subsystems/win32/win32k/objects/dibobj.c b/reactos/subsystems/win32/win32k/objects/dibobj.c index 65bee8e34ee..3bfb4438395 100644 --- a/reactos/subsystems/win32/win32k/objects/dibobj.c +++ b/reactos/subsystems/win32/win32k/objects/dibobj.c @@ -317,7 +317,7 @@ NtGdiSetDIBits( DC_UnlockDc(Dc); return 0; } - + // Need SEH to check Bits and bmi. BTW bmi was converted in gdi. Ret = IntSetDIBits(Dc, hBitmap, StartScan, ScanLines, Bits, bmi, ColorUse); DC_UnlockDc(Dc); @@ -399,7 +399,7 @@ NtGdiSetDIBitsToDeviceInternal( ptSource.y = YSrc; /* Enter SEH, as the bits are user mode */ - _SEH_TRY + _SEH_TRY // Look at NtGdiStretchDIBitsInternal { SourceSize.cx = bmi->bmiHeader.biWidth; SourceSize.cy = ScanLines; @@ -541,8 +541,8 @@ NtGdiGetDIBitsInternal(HDC hDC, /* fill out the BITMAPINFO struct */ if (Bits == NULL) { - _SEH_TRY - { + _SEH_TRY // Look at NtGdiStretchDIBitsInternal + { // Why check for anything, we converted in gdi! if (Info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER)) { BITMAPCOREHEADER* coreheader = (BITMAPCOREHEADER*) Info; @@ -806,6 +806,7 @@ NtGdiStretchDIBitsInternal( HDC hdcMem; HPALETTE hPal = NULL; PDC pDC; + BOOL Hit = FALSE; if (!Bits || !BitsInfo) { @@ -813,6 +814,23 @@ NtGdiStretchDIBitsInternal( return 0; } + _SEH_TRY + { + ProbeForRead(BitsInfo, cjMaxInfo, 1); + ProbeForRead(Bits, cjMaxBits, 1); + } + _SEH_HANDLE + { + Hit = TRUE; + } + _SEH_END + + if (Hit) + { + DPRINT1("NtGdiStretchDIBitsInternal fail to read BitMapInfo: %x or Bits: %x\n",BitsInfo,Bits); + return 0; + } + hdcMem = NtGdiCreateCompatibleDC(hDC); if (hdcMem == NULL) { @@ -993,6 +1011,7 @@ NtGdiCreateDIBitmapInternal(IN HDC hDc, { PDC Dc; HBITMAP Bmp; + UINT bpp; if (!hDc) { // Should use System Bitmap DC hSystemBM, with CreateCompatibleDC for this. @@ -1010,9 +1029,8 @@ NtGdiCreateDIBitmapInternal(IN HDC hDc, SetLastWin32Error(ERROR_INVALID_HANDLE); return NULL; } - - cjMaxInitInfo = 1; - Bmp = IntCreateDIBitmap(Dc, cx, cy, cjMaxInitInfo, fInit, pjInit, pbmi, iUsage); + bpp = IntGdiGetDeviceCaps(Dc, BITSPIXEL); + Bmp = IntCreateDIBitmap(Dc, cx, cy, bpp, fInit, pjInit, pbmi, iUsage); DC_UnlockDc(Dc); NtGdiDeleteObjectApp(hDc); @@ -1025,8 +1043,16 @@ NtGdiCreateDIBitmapInternal(IN HDC hDc, SetLastWin32Error(ERROR_INVALID_HANDLE); return NULL; } + /* pbmi == null + First create an un-initialised bitmap. The depth of the bitmap + should match that of the hdc and not that supplied in bmih. + */ + if (pbmi) + bpp = pbmi->bmiHeader.biBitCount; + else + bpp = IntGdiGetDeviceCaps(Dc, BITSPIXEL); - Bmp = IntCreateDIBitmap(Dc, cx, cy, cjMaxInitInfo, fInit, pjInit, pbmi, iUsage); + Bmp = IntCreateDIBitmap(Dc, cx, cy, bpp, fInit, pjInit, pbmi, iUsage); DC_UnlockDc(Dc); } return Bmp;