mirror of
https://github.com/reactos/reactos.git
synced 2025-07-27 07:41:51 +00:00
[WIN32K]
- 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:
parent
779b528c86
commit
54babc294b
3 changed files with 192 additions and 78 deletions
|
@ -10,4 +10,17 @@ HPALETTE FASTCALL BuildDIBPalette (CONST BITMAPINFO *bmi);
|
||||||
BITMAPINFO* FASTCALL DIB_ConvertBitmapInfo(CONST BITMAPINFO* bmi, DWORD Usage);
|
BITMAPINFO* FASTCALL DIB_ConvertBitmapInfo(CONST BITMAPINFO* bmi, DWORD Usage);
|
||||||
VOID FASTCALL DIB_FreeConvertedBitmapInfo(BITMAPINFO* converted, BITMAPINFO* orig);
|
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
|
#define DIB_PAL_BRUSHHACK 3
|
||||||
|
|
|
@ -565,7 +565,7 @@ Exit2:
|
||||||
/* Converts a device-dependent bitmap to a DIB */
|
/* Converts a device-dependent bitmap to a DIB */
|
||||||
INT
|
INT
|
||||||
APIENTRY
|
APIENTRY
|
||||||
NtGdiGetDIBitsInternal(
|
GreGetDIBitsInternal(
|
||||||
HDC hDC,
|
HDC hDC,
|
||||||
HBITMAP hBitmap,
|
HBITMAP hBitmap,
|
||||||
UINT StartScan,
|
UINT StartScan,
|
||||||
|
@ -587,31 +587,12 @@ NtGdiGetDIBitsInternal(
|
||||||
RGBTRIPLE* rgbTriples;
|
RGBTRIPLE* rgbTriples;
|
||||||
RGBQUAD* rgbQuads;
|
RGBQUAD* rgbQuads;
|
||||||
VOID* colorPtr;
|
VOID* colorPtr;
|
||||||
NTSTATUS Status = STATUS_SUCCESS;
|
|
||||||
|
|
||||||
DPRINT("Entered NtGdiGetDIBitsInternal()\n");
|
DPRINT("Entered NtGdiGetDIBitsInternal()\n");
|
||||||
|
|
||||||
if ((Usage && Usage != DIB_PAL_COLORS) || !Info || !hBitmap)
|
if ((Usage && Usage != DIB_PAL_COLORS) || !Info || !hBitmap)
|
||||||
return 0;
|
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;
|
colorPtr = (LPBYTE)Info + Info->bmiHeader.biSize;
|
||||||
rgbTriples = colorPtr;
|
rgbTriples = colorPtr;
|
||||||
rgbQuads = colorPtr;
|
rgbQuads = colorPtr;
|
||||||
|
@ -834,7 +815,6 @@ NtGdiGetDIBitsInternal(
|
||||||
colorTriple->rgbtRed = (r * 0xff) / 5;
|
colorTriple->rgbtRed = (r * 0xff) / 5;
|
||||||
colorTriple->rgbtGreen = (g * 0xff) / 5;
|
colorTriple->rgbtGreen = (g * 0xff) / 5;
|
||||||
colorTriple->rgbtBlue = (b * 0xff) / 5;
|
colorTriple->rgbtBlue = (b * 0xff) / 5;
|
||||||
color++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -993,24 +973,9 @@ NtGdiGetDIBitsInternal(
|
||||||
if(!ret)
|
if(!ret)
|
||||||
ScanLines = 0;
|
ScanLines = 0;
|
||||||
else
|
else
|
||||||
{
|
|
||||||
Status = STATUS_SUCCESS;
|
|
||||||
_SEH2_TRY
|
|
||||||
{
|
{
|
||||||
RtlCopyMemory(Bits, pDIBits, DIB_GetDIBImageBytes (width, ScanLines, bpp));
|
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
GreDeleteObject(hBmpDest);
|
GreDeleteObject(hBmpDest);
|
||||||
EXLATEOBJ_vCleanup(&exlo);
|
EXLATEOBJ_vCleanup(&exlo);
|
||||||
|
@ -1026,6 +991,109 @@ done:
|
||||||
return ScanLines;
|
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)
|
#define ROP_TO_ROP4(Rop) ((Rop) >> 16)
|
||||||
|
|
||||||
W32KAPI
|
W32KAPI
|
||||||
|
|
|
@ -135,48 +135,81 @@ IntIsClipboardOpenByMe(PWINSTATION_OBJECT pWinSta)
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID static NTAPI
|
VOID static NTAPI
|
||||||
IntSynthesizeDib(PWINSTATION_OBJECT pWinStaObj, HBITMAP hBm)
|
IntSynthesizeDib(
|
||||||
|
PWINSTATION_OBJECT pWinStaObj,
|
||||||
|
HBITMAP hbm)
|
||||||
{
|
{
|
||||||
HDC hdc;
|
HDC hdc;
|
||||||
BITMAP bm;
|
ULONG cjInfoSize, cjDataSize;
|
||||||
BITMAPINFO bi;
|
PCLIPBOARDDATA pClipboardData;
|
||||||
SURFACE *psurf;
|
|
||||||
PCLIPBOARDDATA pMemObj;
|
|
||||||
HANDLE hMem;
|
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);
|
hdc = UserGetDCEx(NULL, NULL, DCX_USESTYLE);
|
||||||
if (!hdc)
|
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;
|
return;
|
||||||
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:
|
cleanup:
|
||||||
UserReleaseDC(NULL, hdc, FALSE);
|
UserReleaseDC(NULL, hdc, FALSE);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue