mirror of
https://github.com/reactos/reactos.git
synced 2024-06-27 08:21:31 +00:00
[0.4.9][WIN32K] Revert NtGdiStretchDIBitsInternal to Previous Logic (#3774)
Fixes gdi32:dib / gdi32:bitmap tests and CORE-16236 "SIMS graphics", which regressed by SVN 51005 == git2bbd8711a7
Thanks to the patches author Doug Lyons. It also fixed CORE-16621 Kompozer 0.7.10 from rapps, exe does not show an icon, but does on 2k3sp2 fix picked from 0.4.15-dev-2850-g847b037fe9
-------------- By taking the above, we also have to pick its addendum [WIN32K] Fix 'use after free' in NtGdiStretchDIBitsInternal #4122 CORE-17861 0.4.15-dev-3420-gb538b9abb8
to avoid introducing another bug: CORE-17861 MS Visual Studio 2010 Pro Fatal System Error 0x00000050 -------------- [WIN32K] Don't trust the BITMAPINFOHEADER size This is not entirely correct yet, but less wrong than before and fixes CORE-16031 Moo0 Audio Recorder - ReactOS icons are not displayed in the system tray fix picked from 0.4.14-dev-848-g53c9a6deaa
This commit is contained in:
parent
e2de354688
commit
af3e03aeef
|
@ -1109,7 +1109,7 @@ NtGdiGetDIBitsInternal(
|
|||
}
|
||||
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
_SEH2_YIELD(goto cleanup;)
|
||||
goto cleanup;
|
||||
}
|
||||
_SEH2_END;
|
||||
|
||||
|
@ -1190,7 +1190,6 @@ NtGdiStretchDIBitsInternal(
|
|||
IN UINT cjMaxBits,
|
||||
IN HANDLE hcmXform)
|
||||
{
|
||||
BOOL bResult = FALSE;
|
||||
SIZEL sizel;
|
||||
RECTL rcSrc, rcDst;
|
||||
PDC pdc;
|
||||
|
@ -1198,7 +1197,69 @@ NtGdiStretchDIBitsInternal(
|
|||
PSURFACE psurfTmp = 0, psurfDst = 0;
|
||||
PPALETTE ppalDIB = 0;
|
||||
EXLATEOBJ exlo;
|
||||
PVOID pvBits;
|
||||
PBYTE pvBits;
|
||||
|
||||
LPBITMAPINFO pbmiSafe;
|
||||
UINT cjAlloc;
|
||||
HBITMAP hBitmap, hOldBitmap = NULL;
|
||||
HDC hdcMem;
|
||||
HPALETTE hPal = NULL;
|
||||
ULONG BmpFormat = 0;
|
||||
INT LinesCopied = 0;
|
||||
|
||||
/* Check for bad iUsage */
|
||||
if (dwUsage > 2) return 0;
|
||||
|
||||
/* We must have LPBITMAPINFO */
|
||||
if (!pbmi)
|
||||
{
|
||||
DPRINT1("Error, Invalid Parameter.\n");
|
||||
EngSetLastError(ERROR_INVALID_PARAMETER);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check if the size of the bitmap info is large enough */
|
||||
if (cjMaxInfo < sizeof(BITMAPCOREHEADER))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Use maximum size */
|
||||
cjMaxInfo = min(cjMaxInfo, sizeof(BITMAPV5HEADER) + 256 * sizeof(RGBQUAD));
|
||||
|
||||
// HACK: the underlying code sucks and doesn't care for the size, so we
|
||||
// give it the maximum ever needed
|
||||
cjAlloc = sizeof(BITMAPV5HEADER) + 256 * sizeof(RGBQUAD);
|
||||
|
||||
/* Allocate a buffer the bitmapinfo */
|
||||
pbmiSafe = ExAllocatePoolWithTag(PagedPool, cjAlloc, 'imBG');
|
||||
if (!pbmiSafe)
|
||||
{
|
||||
/* Fail */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Use SEH */
|
||||
_SEH2_TRY
|
||||
{
|
||||
/* Probe and copy the BITMAPINFO */
|
||||
ProbeForRead(pbmi, cjMaxInfo, 1);
|
||||
RtlCopyMemory(pbmiSafe, pbmi, cjMaxInfo);
|
||||
}
|
||||
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
ExFreePoolWithTag(pbmiSafe, 'imBG');
|
||||
return 0;
|
||||
}
|
||||
_SEH2_END;
|
||||
|
||||
/* Check if the header size is large enough */
|
||||
if ((pbmiSafe->bmiHeader.biSize < sizeof(BITMAPCOREHEADER)) ||
|
||||
(pbmiSafe->bmiHeader.biSize > cjMaxInfo))
|
||||
{
|
||||
ExFreePoolWithTag(pbmiSafe, 'imBG');
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(pdc = DC_LockDc(hdc)))
|
||||
{
|
||||
|
@ -1220,31 +1281,9 @@ NtGdiStretchDIBitsInternal(
|
|||
IntLPtoDP(pdc, (POINTL*)&sizel, 1);
|
||||
DC_UnlockDc(pdc);
|
||||
|
||||
/* Check if we can use NtGdiSetDIBitsToDeviceInternal */
|
||||
if ((sizel.cx == cxSrc) && (sizel.cy == cySrc) && (dwRop == SRCCOPY))
|
||||
{
|
||||
/* Yes, we can! */
|
||||
return NtGdiSetDIBitsToDeviceInternal(hdc,
|
||||
xDst,
|
||||
yDst,
|
||||
cxDst,
|
||||
cyDst,
|
||||
xSrc,
|
||||
ySrc,
|
||||
0,
|
||||
cySrc,
|
||||
pjInit,
|
||||
pbmi,
|
||||
dwUsage,
|
||||
cjMaxBits,
|
||||
cjMaxInfo,
|
||||
TRUE,
|
||||
hcmXform);
|
||||
}
|
||||
|
||||
if (pjInit && (cjMaxBits > 0))
|
||||
{
|
||||
pvBits = ExAllocatePoolWithTag(PagedPool, cjMaxBits, 'pmeT');
|
||||
pvBits = ExAllocatePoolWithTag(PagedPool, cjMaxBits, TAG_DIB);
|
||||
if (!pvBits)
|
||||
{
|
||||
return 0;
|
||||
|
@ -1257,8 +1296,8 @@ NtGdiStretchDIBitsInternal(
|
|||
}
|
||||
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
ExFreePoolWithTag(pvBits, 'pmeT');
|
||||
_SEH2_YIELD(return 0);
|
||||
ExFreePoolWithTag(pvBits, TAG_DIB);
|
||||
return 0;
|
||||
}
|
||||
_SEH2_END;
|
||||
}
|
||||
|
@ -1267,6 +1306,75 @@ NtGdiStretchDIBitsInternal(
|
|||
pvBits = NULL;
|
||||
}
|
||||
|
||||
/* Here we select between the dwRop with SRCCOPY or not. */
|
||||
if (dwRop == SRCCOPY)
|
||||
{
|
||||
hdcMem = NtGdiCreateCompatibleDC(hdc);
|
||||
if (hdcMem == NULL)
|
||||
{
|
||||
DPRINT1("NtGdiCreateCompatibleDC failed to create hdc.\n");
|
||||
EngSetLastError(ERROR_NO_SYSTEM_RESOURCES);
|
||||
return 0;
|
||||
}
|
||||
|
||||
hBitmap = NtGdiCreateCompatibleBitmap(hdc,
|
||||
abs(pbmiSafe->bmiHeader.biWidth),
|
||||
abs(pbmiSafe->bmiHeader.biHeight));
|
||||
if (hBitmap == NULL)
|
||||
{
|
||||
DPRINT1("NtGdiCreateCompatibleBitmap failed to create bitmap.\n");
|
||||
DPRINT1("hdc : 0x%08x \n", hdc);
|
||||
DPRINT1("width : 0x%08x \n", pbmiSafe->bmiHeader.biWidth);
|
||||
DPRINT1("height : 0x%08x \n", pbmiSafe->bmiHeader.biHeight);
|
||||
EngSetLastError(ERROR_NO_SYSTEM_RESOURCES);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Select the bitmap into hdcMem, and save a handle to the old bitmap */
|
||||
hOldBitmap = NtGdiSelectBitmap(hdcMem, hBitmap);
|
||||
|
||||
if (dwUsage == DIB_PAL_COLORS)
|
||||
{
|
||||
hPal = NtGdiGetDCObject(hdc, GDI_OBJECT_TYPE_PALETTE);
|
||||
hPal = GdiSelectPalette(hdcMem, hPal, FALSE);
|
||||
}
|
||||
|
||||
pdc = DC_LockDc(hdcMem);
|
||||
if (pdc != NULL)
|
||||
{
|
||||
IntSetDIBits(pdc, hBitmap, 0, abs(pbmiSafe->bmiHeader.biHeight), pvBits,
|
||||
cjMaxBits, pbmiSafe, dwUsage);
|
||||
DC_UnlockDc(pdc);
|
||||
}
|
||||
|
||||
/* Origin for DIBitmap may be bottom left (positive biHeight) or top
|
||||
left (negative biHeight) */
|
||||
if (cxSrc == cxDst && cySrc == cyDst)
|
||||
{
|
||||
NtGdiBitBlt(hdc, xDst, yDst, cxDst, cyDst,
|
||||
hdcMem, xSrc, abs(pbmiSafe->bmiHeader.biHeight) - cySrc - ySrc,
|
||||
dwRop, 0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
NtGdiStretchBlt(hdc, xDst, yDst, cxDst, cyDst,
|
||||
hdcMem, xSrc, abs(pbmiSafe->bmiHeader.biHeight) - cySrc - ySrc,
|
||||
cxSrc, cySrc, dwRop, 0);
|
||||
}
|
||||
|
||||
/* cleanup */
|
||||
if (hPal)
|
||||
GdiSelectPalette(hdcMem, hPal, FALSE);
|
||||
|
||||
if (hOldBitmap)
|
||||
NtGdiSelectBitmap(hdcMem, hOldBitmap);
|
||||
|
||||
NtGdiDeleteObjectApp(hdcMem);
|
||||
GreDeleteObject(hBitmap);
|
||||
|
||||
} /* End of dwRop == SRCCOPY */
|
||||
else
|
||||
{ /* Start of dwRop != SRCCOPY */
|
||||
/* FIXME: Locking twice is cheesy, coord tranlation in UM will fix it */
|
||||
if (!(pdc = DC_LockDc(hdc)))
|
||||
{
|
||||
|
@ -1292,34 +1400,33 @@ NtGdiStretchDIBitsInternal(
|
|||
IntUpdateBoundsRect(pdc, &rcDst);
|
||||
}
|
||||
|
||||
hbmTmp = GreCreateBitmapEx(pbmi->bmiHeader.biWidth,
|
||||
abs(pbmi->bmiHeader.biHeight),
|
||||
BmpFormat = BitmapFormat(pbmiSafe->bmiHeader.biBitCount,
|
||||
pbmiSafe->bmiHeader.biCompression);
|
||||
|
||||
hbmTmp = GreCreateBitmapEx(pbmiSafe->bmiHeader.biWidth,
|
||||
abs(pbmiSafe->bmiHeader.biHeight),
|
||||
0,
|
||||
BitmapFormat(pbmi->bmiHeader.biBitCount,
|
||||
pbmi->bmiHeader.biCompression),
|
||||
pbmi->bmiHeader.biHeight < 0 ? BMF_TOPDOWN : 0,
|
||||
pbmi->bmiHeader.biSizeImage,
|
||||
BmpFormat,
|
||||
pbmiSafe->bmiHeader.biHeight < 0 ? BMF_TOPDOWN : 0,
|
||||
cjMaxBits,
|
||||
pvBits,
|
||||
0);
|
||||
|
||||
if (!hbmTmp)
|
||||
{
|
||||
bResult = FALSE;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
psurfTmp = SURFACE_ShareLockSurface(hbmTmp);
|
||||
if (!psurfTmp)
|
||||
{
|
||||
bResult = FALSE;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Create a palette for the DIB */
|
||||
ppalDIB = CreateDIBPalette(pbmi, pdc, dwUsage);
|
||||
ppalDIB = CreateDIBPalette(pbmiSafe, pdc, dwUsage);
|
||||
if (!ppalDIB)
|
||||
{
|
||||
bResult = FALSE;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
|
@ -1337,7 +1444,7 @@ NtGdiStretchDIBitsInternal(
|
|||
pdc->pdcattr->crForegroundClr);
|
||||
|
||||
/* Perform the stretch operation */
|
||||
bResult = IntEngStretchBlt(&psurfDst->SurfObj,
|
||||
IntEngStretchBlt(&psurfDst->SurfObj,
|
||||
&psurfTmp->SurfObj,
|
||||
NULL,
|
||||
(CLIPOBJ *)&pdc->co,
|
||||
|
@ -1353,14 +1460,31 @@ NtGdiStretchDIBitsInternal(
|
|||
/* Cleanup */
|
||||
DC_vFinishBlit(pdc, NULL);
|
||||
EXLATEOBJ_vCleanup(&exlo);
|
||||
|
||||
cleanup:
|
||||
if (ppalDIB) PALETTE_ShareUnlockPalette(ppalDIB);
|
||||
if (psurfTmp) SURFACE_ShareUnlockSurface(psurfTmp);
|
||||
if (hbmTmp) GreDeleteObject(hbmTmp);
|
||||
if (pdc) DC_UnlockDc(pdc);
|
||||
if (pvBits) ExFreePoolWithTag(pvBits, 'pmeT');
|
||||
}
|
||||
|
||||
return bResult;
|
||||
if (pvBits) ExFreePoolWithTag(pvBits, TAG_DIB);
|
||||
|
||||
/* This is not what MSDN says is returned from this function, but it
|
||||
* follows Wine's dlls/gdi32/dib.c function nulldrv_StretchDIBits
|
||||
* and it fixes over 100 gdi32:dib regression tests. */
|
||||
if (dwRop == SRCCOPY)
|
||||
{
|
||||
LinesCopied = abs(pbmiSafe->bmiHeader.biHeight);
|
||||
}
|
||||
else
|
||||
{
|
||||
LinesCopied = pbmiSafe->bmiHeader.biHeight;
|
||||
}
|
||||
|
||||
ExFreePoolWithTag(pbmiSafe, 'imBG');
|
||||
|
||||
return LinesCopied;
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue