Author: tkreuzer
Date: Sun Sep 30 20:30:23 2012
New Revision: 57443
URL:
http://svn.reactos.org/svn/reactos?rev=57443&view=rev
Log:
[WIN32K]
- Seperate GreGetDIBitsInternal from NtGdiGetDIBitsInternal
- Rewrite IntSynthesizeDib
- Fixes heap corruption when doing screen shots or copying from paint
CORE-6674 CORE-6093 #resolve
Modified:
trunk/reactos/win32ss/gdi/ntgdi/dib.h
trunk/reactos/win32ss/gdi/ntgdi/dibobj.c
trunk/reactos/win32ss/user/ntuser/clipboard.c
Modified: trunk/reactos/win32ss/gdi/ntgdi/dib.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/gdi/ntgdi/dib.h?re…
==============================================================================
--- trunk/reactos/win32ss/gdi/ntgdi/dib.h [iso-8859-1] (original)
+++ trunk/reactos/win32ss/gdi/ntgdi/dib.h [iso-8859-1] Sun Sep 30 20:30:23 2012
@@ -10,4 +10,17 @@
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
Modified: trunk/reactos/win32ss/gdi/ntgdi/dibobj.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/gdi/ntgdi/dibobj.c…
==============================================================================
--- trunk/reactos/win32ss/gdi/ntgdi/dibobj.c [iso-8859-1] (original)
+++ trunk/reactos/win32ss/gdi/ntgdi/dibobj.c [iso-8859-1] Sun Sep 30 20:30:23 2012
@@ -465,7 +465,7 @@
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 @@
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 @@
ret = ScanLines;
goto Exit;
}
-
+
ASSERT(pSurf->ppal);
/* Initialize EXLATEOBJ */
@@ -520,7 +520,7 @@
RGB(0xff, 0xff, 0xff),
pDC->pdcattr->crBackgroundClr,
pDC->pdcattr->crForegroundClr);
-
+
pDestSurf = &pSurf->SurfObj;
/* Copy the bits */
@@ -541,7 +541,7 @@
/* Cleanup EXLATEOBJ */
EXLATEOBJ_vCleanup(&exlo);
-
+
/* We're done */
DC_vFinishBlit(pDC, NULL);
@@ -565,7 +565,7 @@
/* Converts a device-dependent bitmap to a DIB */
INT
APIENTRY
-NtGdiGetDIBitsInternal(
+GreGetDIBitsInternal(
HDC hDC,
HBITMAP hBitmap,
UINT StartScan,
@@ -587,30 +587,11 @@
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;
@@ -834,7 +815,6 @@
colorTriple->rgbtRed = (r * 0xff) / 5;
colorTriple->rgbtGreen = (g * 0xff) / 5;
colorTriple->rgbtBlue = (b * 0xff) / 5;
- color++;
}
}
}
@@ -994,22 +974,7 @@
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);
@@ -1025,6 +990,109 @@
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)
@@ -1129,7 +1197,7 @@
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 @@
/* Prepare DC for blit */
DC_vPrepareDCsForBlit(pdc, rcDst, NULL, rcSrc);
-
+
psurfDst = pdc->dclevel.pSurface;
if (!psurfDst)
{
@@ -1172,7 +1240,7 @@
bResult = TRUE;
goto cleanup;
}
-
+
/* Initialize XLATEOBJ */
EXLATEOBJ_vInitialize(&exlo,
ppalDIB,
Modified: trunk/reactos/win32ss/user/ntuser/clipboard.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/user/ntuser/clipbo…
==============================================================================
--- trunk/reactos/win32ss/user/ntuser/clipboard.c [iso-8859-1] (original)
+++ trunk/reactos/win32ss/user/ntuser/clipboard.c [iso-8859-1] Sun Sep 30 20:30:23 2012
@@ -135,47 +135,80 @@
}
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);
- }
+ }
+
+ /* 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);