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..32daf767551 100644 --- a/win32ss/gdi/gdi32/objects/bitmap.c +++ b/win32ss/gdi/gdi32/objects/bitmap.c @@ -209,6 +209,12 @@ CreateDIBSection( HBITMAP hBitmap = NULL; PVOID bmBits = NULL; + if (Usage != DIB_PAL_COLORS && Usage != DIB_RGB_COLORS) + { + SetLastError(ERROR_INVALID_PARAMETER); + return NULL; + } + pConvertedInfo = ConvertBitmapInfo(BitmapInfo, Usage, &ConvertedInfoSize, FALSE); @@ -577,6 +583,9 @@ SetDIBits( INT LinesCopied = 0; BOOL newDC = FALSE; + if (fuColorUse != DIB_PAL_COLORS && fuColorUse != DIB_RGB_COLORS) + return 0; + if (!lpvBits || (GDI_HANDLE_GET_TYPE(hBitmap) != GDI_OBJECT_TYPE_BITMAP)) return 0; @@ -664,10 +673,14 @@ SetDIBitsToDevice( UINT ConvertedInfoSize; INT LinesCopied = 0; UINT cjBmpScanSize = 0; - BOOL Hit = FALSE; + BOOL Hit = FALSE, Hit2= FALSE; PVOID pvSafeBits = (PVOID) Bits; + // VMware maximum resolution is 2048 x 1536 + INT MaxScreenLines = 1536; + // Arbitrary number for Maximum StartScan + INT MaxStartScan = LONG_MAX / 2; - if (!ScanLines || !lpbmi || !Bits) + if (!ScanLines || !lpbmi || !Bits || (Height == 0)) return 0; if (ColorUse && ColorUse != DIB_PAL_COLORS && ColorUse != DIB_PAL_COLORS + 1) @@ -677,6 +690,46 @@ SetDIBitsToDevice( if (!pConvertedInfo) return 0; + if (pConvertedInfo->bmiHeader.biHeight == 0) + { + return 0; + } + + // If DIB Height is big negative amd StartScan not huge + if ((lpbmi->bmiHeader.biHeight < -MaxScreenLines) && + (StartScan < MaxStartScan)) + { + 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 and lpbmi biHeight not too big + 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 +795,42 @@ SetDIBitsToDevice( { Hit = TRUE; } - _SEH2_END + _SEH2_END; + + /* The caller might be sending "just enough" data. Setting ScanLines as Height */ + if ((ScanLines > Height) && (StartScan < MaxStartScan)) + { + 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); + + DPRINT("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) + { + DPRINT("SetDIBitsToDevice second fail.\n"); + } + // Cannot read either + if (Hit && Hit2) + { + LinesCopied = 0; + goto Exit; + } + } DPRINT("SetDIBitsToDevice Allocate Bits %u!!!\n", cjBmpScanSize); } @@ -837,6 +918,16 @@ StretchDIBits( return 0; } + if (pConvertedInfo->bmiHeader.biWidth < 0) + { + return 0; + } + + if (pConvertedInfo->bmiHeader.biHeight == 0) + { + return 0; + } + cjBmpScanSize = GdiGetBitmapBitsSize((BITMAPINFO *) pConvertedInfo); if (lpBits)