diff --git a/win32ss/gdi/gdi32/objects/bitmap.c b/win32ss/gdi/gdi32/objects/bitmap.c index b029d4ad2df..c40e22ff8fa 100644 --- a/win32ss/gdi/gdi32/objects/bitmap.c +++ b/win32ss/gdi/gdi32/objects/bitmap.c @@ -666,6 +666,10 @@ SetDIBitsToDevice( UINT cjBmpScanSize = 0; BOOL Hit = FALSE; PVOID pvSafeBits = (PVOID) Bits; + UINT bmiHeight; + + #define aligned(Address, Count) \ + (((ULONG_PTR)(void *)(Address)) % (Count) == 0) if (!ScanLines || !lpbmi || !Bits) return 0; @@ -677,6 +681,61 @@ SetDIBitsToDevice( if (!pConvertedInfo) return 0; + if (pConvertedInfo->bmiHeader.biHeight == 0) + { + return 0; + } + + if (!aligned(Bits, 4) && (ScanLines > Height)) + { + return 0; + } + + /* Below code modeled after Wine's nulldrv_SetDIBitsToDevice */ + bmiHeight = abs(pConvertedInfo->bmiHeader.biHeight); + if (StartScan <= YSrc + bmiHeight) + { + BOOL top_down; + UINT src_y = 0; + + top_down = (pConvertedInfo->bmiHeader.biHeight < 0); + if ((pConvertedInfo->bmiHeader.biCompression == BI_RLE8) || + (pConvertedInfo->bmiHeader.biCompression == BI_RLE4)) + { + StartScan = 0; + ScanLines = bmiHeight; + } + else + { + if (StartScan >= bmiHeight) + { + return 0; + } + if (!top_down && ScanLines > bmiHeight - StartScan) + { + ScanLines = bmiHeight - StartScan; + } + src_y = StartScan + ScanLines - (YSrc + Height); + if (src_y > 0) + { + if (!top_down) + { + /* get rid of unnecessary lines */ + if (src_y >= ScanLines) + { + return 0; + } + ScanLines -= src_y; + } + else if (src_y >= ScanLines) + { + return ScanLines; + } + } + LinesCopied = ScanLines; + } + } + HANDLE_METADC(INT, SetDIBitsToDevice, 0, diff --git a/win32ss/gdi/ntgdi/dibobj.c b/win32ss/gdi/ntgdi/dibobj.c index ec5fa69a469..f01b0fd5106 100644 --- a/win32ss/gdi/ntgdi/dibobj.c +++ b/win32ss/gdi/ntgdi/dibobj.c @@ -518,7 +518,10 @@ NtGdiSetDIBitsToDeviceInternal( } _SEH2_END; - ScanLines = min(ScanLines, abs(bmi->bmiHeader.biHeight) - StartScan); + ScanLines = min(abs(Height),ScanLines); + if (YSrc > 0) + ScanLines += YSrc; + if (ScanLines == 0) { DPRINT1("ScanLines == 0\n"); @@ -562,6 +565,8 @@ NtGdiSetDIBitsToDeviceInternal( SourceSize.cx = bmi->bmiHeader.biWidth; SourceSize.cy = ScanLines; + if (YSrc > 0) + ScanLines += YSrc; //DIBWidth = WIDTH_BYTES_ALIGN32(SourceSize.cx, bmi->bmiHeader.biBitCount);