- Seperate GreGetDIBitsInternal from NtGdiGetDIBitsInternal
- Rewrite IntSynthesizeDib
- Fixes heap corruption when doing screen shots or copying from paint
CORE-6674 CORE-6093 #resolve

svn path=/trunk/; revision=57443
This commit is contained in:
Timo Kreuzer 2012-09-30 20:30:23 +00:00
parent 779b528c86
commit 54babc294b
3 changed files with 192 additions and 78 deletions

View file

@ -10,4 +10,17 @@ HPALETTE FASTCALL BuildDIBPalette (CONST BITMAPINFO *bmi);
BITMAPINFO* FASTCALL DIB_ConvertBitmapInfo(CONST BITMAPINFO* bmi, DWORD Usage);
VOID FASTCALL DIB_FreeConvertedBitmapInfo(BITMAPINFO* converted, BITMAPINFO* orig);
INT
APIENTRY
GreGetDIBitsInternal(
HDC hDC,
HBITMAP hBitmap,
UINT StartScan,
UINT ScanLines,
LPBYTE Bits,
LPBITMAPINFO Info,
UINT Usage,
UINT MaxBits,
UINT MaxInfo);
#define DIB_PAL_BRUSHHACK 3

View file

@ -465,7 +465,7 @@ NtGdiSetDIBitsToDeviceInternal(
SourceSize.cx = bmi->bmiHeader.biWidth;
SourceSize.cy = ScanLines;
//DIBWidth = WIDTH_BYTES_ALIGN32(SourceSize.cx, bmi->bmiHeader.biBitCount);
hSourceBitmap = GreCreateBitmapEx(bmi->bmiHeader.biWidth,
@ -500,7 +500,7 @@ NtGdiSetDIBitsToDeviceInternal(
Status = STATUS_NO_MEMORY;
goto Exit;
}
/* This is actually a blit */
DC_vPrepareDCsForBlit(pDC, rcDest, NULL, rcDest);
pSurf = pDC->dclevel.pSurface;
@ -510,7 +510,7 @@ NtGdiSetDIBitsToDeviceInternal(
ret = ScanLines;
goto Exit;
}
ASSERT(pSurf->ppal);
/* Initialize EXLATEOBJ */
@ -520,7 +520,7 @@ NtGdiSetDIBitsToDeviceInternal(
RGB(0xff, 0xff, 0xff),
pDC->pdcattr->crBackgroundClr,
pDC->pdcattr->crForegroundClr);
pDestSurf = &pSurf->SurfObj;
/* Copy the bits */
@ -541,7 +541,7 @@ NtGdiSetDIBitsToDeviceInternal(
/* Cleanup EXLATEOBJ */
EXLATEOBJ_vCleanup(&exlo);
/* We're done */
DC_vFinishBlit(pDC, NULL);
@ -565,7 +565,7 @@ Exit2:
/* Converts a device-dependent bitmap to a DIB */
INT
APIENTRY
NtGdiGetDIBitsInternal(
GreGetDIBitsInternal(
HDC hDC,
HBITMAP hBitmap,
UINT StartScan,
@ -587,31 +587,12 @@ NtGdiGetDIBitsInternal(
RGBTRIPLE* rgbTriples;
RGBQUAD* rgbQuads;
VOID* colorPtr;
NTSTATUS Status = STATUS_SUCCESS;
DPRINT("Entered NtGdiGetDIBitsInternal()\n");
if ((Usage && Usage != DIB_PAL_COLORS) || !Info || !hBitmap)
return 0;
_SEH2_TRY
{
/* Probe for read and write */
ProbeForRead(Info, MaxInfo, 1);
ProbeForWrite(Info, MaxInfo, 1);
if (Bits) ProbeForWrite(Bits, MaxBits, 1);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
Status = _SEH2_GetExceptionCode();
}
_SEH2_END
if (!NT_SUCCESS(Status))
{
return 0;
}
colorPtr = (LPBYTE)Info + Info->bmiHeader.biSize;
rgbTriples = colorPtr;
rgbQuads = colorPtr;
@ -834,7 +815,6 @@ NtGdiGetDIBitsInternal(
colorTriple->rgbtRed = (r * 0xff) / 5;
colorTriple->rgbtGreen = (g * 0xff) / 5;
colorTriple->rgbtBlue = (b * 0xff) / 5;
color++;
}
}
}
@ -994,22 +974,7 @@ NtGdiGetDIBitsInternal(
ScanLines = 0;
else
{
Status = STATUS_SUCCESS;
_SEH2_TRY
{
RtlCopyMemory(Bits, pDIBits, DIB_GetDIBImageBytes (width, ScanLines, bpp));
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
Status = _SEH2_GetExceptionCode();
}
_SEH2_END
if(!NT_SUCCESS(Status))
{
DPRINT1("Unable to copy bits to the user provided pointer\n");
ScanLines = 0;
}
RtlCopyMemory(Bits, pDIBits, DIB_GetDIBImageBytes (width, ScanLines, bpp));
}
GreDeleteObject(hBmpDest);
@ -1026,6 +991,109 @@ done:
return ScanLines;
}
INT
APIENTRY
NtGdiGetDIBitsInternal(
_In_ HDC hdc,
_In_ HBITMAP hbm,
_In_ UINT iStartScan,
_In_ UINT cScans,
_Out_opt_ LPBYTE pjBits,
_Inout_ LPBITMAPINFO pbmiUser,
_In_ UINT iUsage,
_In_ UINT cjMaxBits,
_In_ UINT cjMaxInfo)
{
PBITMAPINFO pbmi;
HANDLE hSecure = NULL;
INT iResult = 0;
/* Check for bad iUsage */
if (iUsage > 2) return 0;
/* Check if the size of the bitmap info is large enough */
if (cjMaxInfo < sizeof(BITMAPINFOHEADER))
{
return 0;
}
/* Use maximum size */
cjMaxInfo = min(cjMaxInfo, sizeof(BITMAPV5HEADER) + 256 * sizeof(RGBQUAD));
/* Allocate a buffer the bitmapinfo */
pbmi = ExAllocatePoolWithTag(PagedPool, cjMaxInfo, 'imBG');
if (!pbmi)
{
/* Fail */
return 0;
}
/* Use SEH */
_SEH2_TRY
{
/* Probe and copy the BITMAPINFO */
ProbeForWrite(pbmiUser, cjMaxInfo, 1);
RtlCopyMemory(pbmi, pbmiUser, cjMaxInfo);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
_SEH2_YIELD(goto cleanup;)
}
_SEH2_END;
/* Check if the header size is large enough */
if ((pbmi->bmiHeader.biSize < sizeof(BITMAPINFOHEADER)) ||
(pbmi->bmiHeader.biSize > cjMaxInfo))
{
goto cleanup;
}
/* Check if the caller provided bitmap bits */
if (pjBits)
{
/* Secure the user mode memory */
hSecure = EngSecureMem(pjBits, cjMaxBits);
if (!hSecure)
{
goto cleanup;
}
}
/* Now call the internal function */
iResult = GreGetDIBitsInternal(hdc,
hbm,
iStartScan,
cScans,
pjBits,
pbmi,
iUsage,
cjMaxBits,
cjMaxInfo);
/* Check for success */
if (iResult)
{
/* Use SEH to copy back to user mode */
_SEH2_TRY
{
/* Buffer is already probed, copy the data back */
RtlCopyMemory(pbmiUser, pbmi, cjMaxInfo);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
/* Ignore */
}
_SEH2_END;
}
cleanup:
if (hSecure) EngUnsecureMem(hSecure);
ExFreePoolWithTag(pbmi, 'imBG');
return iResult;
}
#define ROP_TO_ROP4(Rop) ((Rop) >> 16)
W32KAPI
@ -1129,7 +1197,7 @@ NtGdiStretchDIBitsInternal(
rcDst.bottom = rcDst.top + cyDst;
IntLPtoDP(pdc, (POINTL*)&rcDst, 2);
RECTL_vOffsetRect(&rcDst, pdc->ptlDCOrig.x, pdc->ptlDCOrig.y);
hbmTmp = GreCreateBitmapEx(pbmi->bmiHeader.biWidth,
pbmi->bmiHeader.biHeight,
0,
@ -1163,7 +1231,7 @@ NtGdiStretchDIBitsInternal(
/* Prepare DC for blit */
DC_vPrepareDCsForBlit(pdc, rcDst, NULL, rcSrc);
psurfDst = pdc->dclevel.pSurface;
if (!psurfDst)
{
@ -1172,7 +1240,7 @@ NtGdiStretchDIBitsInternal(
bResult = TRUE;
goto cleanup;
}
/* Initialize XLATEOBJ */
EXLATEOBJ_vInitialize(&exlo,
ppalDIB,

View file

@ -135,48 +135,81 @@ IntIsClipboardOpenByMe(PWINSTATION_OBJECT pWinSta)
}
VOID static NTAPI
IntSynthesizeDib(PWINSTATION_OBJECT pWinStaObj, HBITMAP hBm)
IntSynthesizeDib(
PWINSTATION_OBJECT pWinStaObj,
HBITMAP hbm)
{
HDC hdc;
BITMAP bm;
BITMAPINFO bi;
SURFACE *psurf;
PCLIPBOARDDATA pMemObj;
ULONG cjInfoSize, cjDataSize;
PCLIPBOARDDATA pClipboardData;
HANDLE hMem;
INT iResult;
struct
{
BITMAPINFOHEADER bmih;
RGBQUAD rgbColors[256];
} bmiBuffer;
PBITMAPINFO pbmi = (PBITMAPINFO)&bmiBuffer;
/* Get the display DC */
hdc = UserGetDCEx(NULL, NULL, DCX_USESTYLE);
if (!hdc)
return;
psurf = SURFACE_ShareLockSurface(hBm);
if (!psurf)
goto cleanup;
BITMAP_GetObject(psurf, sizeof(BITMAP), (PVOID)&bm);
SURFACE_ShareUnlockSurface(psurf);
bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bi.bmiHeader.biWidth = bm.bmWidth;
bi.bmiHeader.biHeight = bm.bmHeight;
bi.bmiHeader.biPlanes = bm.bmPlanes;
bi.bmiHeader.biBitCount = bm.bmBitsPixel;
bi.bmiHeader.biCompression = BI_RGB;
bi.bmiHeader.biSizeImage = 0;
bi.bmiHeader.biXPelsPerMeter = 0;
bi.bmiHeader.biYPelsPerMeter = 0;
bi.bmiHeader.biClrUsed = 0;
NtGdiGetDIBitsInternal(hdc, hBm, 0, bm.bmHeight, NULL, &bi, DIB_RGB_COLORS, 0, 0);
pMemObj = (PCLIPBOARDDATA)UserCreateObject(gHandleTable, NULL, &hMem, otClipBoardData,
sizeof(BITMAPINFOHEADER) + bi.bmiHeader.biSizeImage);
if(pMemObj)
{
pMemObj->cbData = sizeof(BITMAPINFOHEADER) + bi.bmiHeader.biSizeImage;
memcpy(pMemObj->Data, &bi, sizeof(BITMAPINFOHEADER));
NtGdiGetDIBitsInternal(hdc, hBm, 0, bm.bmHeight, (LPBYTE)pMemObj->Data + sizeof(BITMAPINFOHEADER), &bi, DIB_RGB_COLORS, 0, 0);
IntAddFormatedData(pWinStaObj, CF_DIB, hMem, TRUE, TRUE);
return;
}
/* Get information about the bitmap format */
iResult = GreGetDIBitsInternal(hdc,
hbm,
0,
0,
NULL,
pbmi,
DIB_RGB_COLORS,
0,
sizeof(bmiBuffer));
if (iResult == 0)
{
goto cleanup;
}
/* Get the size for a full BITMAPINFO */
cjInfoSize = DIB_BitmapInfoSize(pbmi, DIB_RGB_COLORS);
/* Calculate the size of the clipboard data, which is a packed DIB */
cjDataSize = cjInfoSize + pbmi->bmiHeader.biSizeImage;
/* Create the clipboard data */
pClipboardData = (PCLIPBOARDDATA)UserCreateObject(gHandleTable,
NULL,
&hMem,
otClipBoardData,
cjDataSize);
if (!pClipboardData)
{
goto cleanup;
}
/* Set the data size */
pClipboardData->cbData = cjDataSize;
/* Copy the BITMAPINFOHEADER */
memcpy(pClipboardData->Data, pbmi, sizeof(BITMAPINFOHEADER));
/* Get the bitmap bits and the color table */
iResult = GreGetDIBitsInternal(hdc,
hbm,
0,
abs(pbmi->bmiHeader.biHeight),
(LPBYTE)pClipboardData->Data + cjInfoSize,
(LPBITMAPINFO)pClipboardData->Data,
DIB_RGB_COLORS,
pbmi->bmiHeader.biSizeImage,
cjInfoSize);
/* Add the clipboard data */
IntAddFormatedData(pWinStaObj, CF_DIB, hMem, TRUE, TRUE);
cleanup:
UserReleaseDC(NULL, hdc, FALSE);
}