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); }