diff --git a/modules/rostests/apitests/gdi32/SetDIBitsToDevice.c b/modules/rostests/apitests/gdi32/SetDIBitsToDevice.c index 6e35b0d0afe..e8ce3830205 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 */ @@ -146,7 +146,7 @@ Test_SetDIBitsToDevice_Params() (BYTE*)0x7fffffff, // lpvBits, pbmi, DIB_RGB_COLORS); - todo_ros ok_dec(ret, 0); + ok_dec(ret, 0); ok_err(0xdeadc0de); /* Test negative XDest */ @@ -248,7 +248,7 @@ Test_SetDIBitsToDevice_Params() aulBits, // lpvBits, pbmi, DIB_RGB_COLORS); - todo_ros ok_dec(ret, 7); + ok_dec(ret, 7); ok_err(0xdeadc0de); /* Test large cScanlines */ @@ -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 */ diff --git a/win32ss/gdi/gdi32/objects/bitmap.c b/win32ss/gdi/gdi32/objects/bitmap.c index 438521f69e9..c8ff9f802b6 100644 --- a/win32ss/gdi/gdi32/objects/bitmap.c +++ b/win32ss/gdi/gdi32/objects/bitmap.c @@ -664,8 +664,9 @@ SetDIBitsToDevice( UINT ConvertedInfoSize; INT LinesCopied = 0; UINT cjBmpScanSize = 0; - BOOL Hit = FALSE; + BOOL Hit = FALSE, Hit2= FALSE; PVOID pvSafeBits = (PVOID) Bits; + INT MaxScreenLines = 1536; if (!ScanLines || !lpbmi || !Bits) return 0; @@ -677,6 +678,40 @@ SetDIBitsToDevice( if (!pConvertedInfo) return 0; + // If DIB Height is big negative + if (lpbmi->bmiHeader.biHeight < -MaxScreenLines) + { + return ScanLines; + } + + // If ScanLines are huge positive + if ((ScanLines > MaxScreenLines) || (lpbmi->bmiHeader.biHeight > MaxScreenLines)) + { + LinesCopied = 0; + goto Exit; + } + + // If ScanLines > DIB + if (ScanLines > abs(lpbmi->bmiHeader.biHeight)) + { + LinesCopied = ScanLines; + goto Exit; + } + + // If DIB height > Height + if ((ScanLines > MaxScreenLines) || (abs(lpbmi->bmiHeader.biHeight) > MaxScreenLines)) + { + LinesCopied = 0; + goto Exit; + } + + // If ScanLines > DIB + if (ScanLines > abs(lpbmi->bmiHeader.biHeight)) + { + LinesCopied = ScanLines; + goto Exit; + } + HANDLE_METADC(INT, SetDIBitsToDevice, 0, @@ -742,14 +777,42 @@ SetDIBitsToDevice( { Hit = TRUE; } - _SEH2_END + _SEH2_END; + + /* The caller might be sending "just enough" data. Setting ScanLines as Height */ + if (ScanLines > Height) + { + ScanLines = Height; + cjBmpScanSize = DIB_BitmapMaxBitsSize((LPBITMAPINFO) lpbmi, Height); + } if (Hit) { // We don't die, we continue on with a allocated safe pointer to kernel // space..... - DPRINT1("SetDIBitsToDevice fail to read BitMapInfo: %p or Bits: %p & Size: %u\n", - pConvertedInfo, Bits, cjBmpScanSize); + + DPRINT1("SetDIBitsToDevice fail to read BitMapInfo: %p or Bits: %p & Size: %u Height: %u ScanLines: %u.\n", + pConvertedInfo, Bits, cjBmpScanSize, Height, ScanLines); + _SEH2_TRY + { + RtlCopyMemory(pvSafeBits, Bits, cjBmpScanSize); + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + Hit2 = TRUE; + } + _SEH2_END; + if (Hit) + { + DPRINT1("SetDIBitsToDevice second fail.\n"); + } + // Cannot read either + if (Hit && Hit2) + { + LinesCopied = 0; + goto Exit; + } + } DPRINT("SetDIBitsToDevice Allocate Bits %u!!!\n", cjBmpScanSize); }