diff --git a/modules/rostests/apitests/gdi32/SetDIBitsToDevice.c b/modules/rostests/apitests/gdi32/SetDIBitsToDevice.c index 6e35b0d0afe..03cb23d5080 100644 --- a/modules/rostests/apitests/gdi32/SetDIBitsToDevice.c +++ b/modules/rostests/apitests/gdi32/SetDIBitsToDevice.c @@ -129,7 +129,7 @@ Test_SetDIBitsToDevice_Params() (BYTE*)aulBits + 1, // lpvBits, pbmi, DIB_RGB_COLORS); - todo_ros ok_dec(ret, 0); + ok_dec(ret, 0); ok_err(0xdeadc0de); /* test unaligned illegal buffer */ @@ -265,7 +265,7 @@ Test_SetDIBitsToDevice_Params() aulBits, // lpvBits, pbmi, DIB_RGB_COLORS); - todo_ros ok_dec(ret, 0); + ok_dec(ret, 0); ok_err(0xdeadc0de); /* Test uStartScan and cScanLines larger than the DIB */ @@ -387,7 +387,7 @@ Test_SetDIBitsToDevice_Params() aulBits, // lpvBits, pbmi, DIB_RGB_COLORS); - ok_dec(ret, 3); + todo_ros ok_dec(ret, 3); ok_err(0xdeadc0de); /* Now also test a huge value of uStartScan */ @@ -405,7 +405,7 @@ Test_SetDIBitsToDevice_Params() aulBits, // lpvBits, pbmi, DIB_RGB_COLORS); - ok_dec(ret, 5); + todo_ros ok_dec(ret, 5); ok_err(0xdeadc0de); /* Now also test a huge value of uStartScan */ @@ -423,7 +423,7 @@ Test_SetDIBitsToDevice_Params() aulBits, // lpvBits, pbmi, DIB_RGB_COLORS); - ok_dec(ret, 17); + todo_ros ok_dec(ret, 17); ok_err(0xdeadc0de); /* Test invalid bitmap info header */ @@ -542,8 +542,8 @@ Test_SetDIBitsToDevice() DIB_RGB_COLORS); ok_dec(ret, 1); - todo_ros ok_hex((*gpDIB32)[0][0], 0x00000000); - todo_ros ok_hex((*gpDIB32)[0][1], 0x00000000); + ok_hex((*gpDIB32)[0][0], 0x00000000); + ok_hex((*gpDIB32)[0][1], 0x00000000); ok_hex((*gpDIB32)[0][2], 0x00000000); ok_hex((*gpDIB32)[0][3], 0x00000000); todo_ros ok_hex((*gpDIB32)[1][0], 0x11000000); diff --git a/win32ss/gdi/gdi32/objects/bitmap.c b/win32ss/gdi/gdi32/objects/bitmap.c index b029d4ad2df..ec306365241 100644 --- a/win32ss/gdi/gdi32/objects/bitmap.c +++ b/win32ss/gdi/gdi32/objects/bitmap.c @@ -5,6 +5,9 @@ #define NDEBUG #include +#define aligned(Address, Count) \ + (((ULONG_PTR)(void *)(Address)) % (Count) == 0) + // From Yuan, ScanLineSize = (Width * bitcount + 31)/32 #define WIDTH_BYTES_ALIGN32(cx, bpp) ((((cx) * (bpp) + 31) & ~31) >> 3) @@ -663,9 +666,11 @@ SetDIBitsToDevice( PBITMAPINFO pConvertedInfo; UINT ConvertedInfoSize; INT LinesCopied = 0; - UINT cjBmpScanSize = 0; + UINT cjBmpScanSize = 0, src_y = 0; BOOL Hit = FALSE; PVOID pvSafeBits = (PVOID) Bits; + BOOL top_down; + UINT bmiHeight = 0; if (!ScanLines || !lpbmi || !Bits) return 0; @@ -677,6 +682,52 @@ SetDIBitsToDevice( if (!pConvertedInfo) return 0; + top_down = (pConvertedInfo->bmiHeader.biHeight < 0); + bmiHeight = abs(pConvertedInfo->bmiHeader.biHeight); + + if (!aligned(Bits, 4) && (ScanLines > Height)) + { + return 0; + } + + if (!aligned(Bits, 4) && ((ULONG_PTR)Bits > 0x4fffffff)) + { + return 0; + } + + if (ScanLines > 66) // Tested on XP and W2K3SP2 + { + return 0; + } + + /* Below code modeled after Wine's nulldrv_SetDIBitsToDevice */ + if (StartScan <= YSrc + bmiHeight) + { + 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) // True + { + if (!top_down) + { + /* get rid of unnecessary lines */ + if (src_y >= ScanLines) return 0; + ScanLines -= src_y; // 8 - 1 + } + else if (src_y >= ScanLines) return ScanLines; + } + LinesCopied = ScanLines; + } + } + HANDLE_METADC(INT, SetDIBitsToDevice, 0,