* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
- * $Id: brush.c,v 1.34 2004/04/09 20:03:20 navaraf Exp $
+ * $Id$
*/
-#undef WIN32_LEAN_AND_MEAN
-#include <windows.h>
-#include <ddk/ntddk.h>
-#include <win32k/bitmaps.h>
-#include <win32k/brush.h>
-#include <internal/safe.h>
-#include <include/object.h>
-#include <include/inteng.h>
-#include <include/error.h>
-#include <include/tags.h>
+#include <w32k.h>
+
#define NDEBUG
-#include <win32k/debug1.h>
+#include <debug.h>
+
+static const USHORT HatchBrushes[NB_HATCH_STYLES][8] =
+{
+ {0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00}, /* HS_HORIZONTAL */
+ {0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08}, /* HS_VERTICAL */
+ {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80}, /* HS_FDIAGONAL */
+ {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01}, /* HS_BDIAGONAL */
+ {0x08, 0x08, 0x08, 0xff, 0x08, 0x08, 0x08, 0x08}, /* HS_CROSS */
+ {0x81, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x81} /* HS_DIAGCROSS */
+};
+
+BOOL INTERNAL_CALL
+BRUSH_Cleanup(PVOID ObjectBody)
+{
+ PGDIBRUSHOBJ pBrush = (PGDIBRUSHOBJ)ObjectBody;
+ if(pBrush->flAttrs & (GDIBRUSH_IS_HATCH | GDIBRUSH_IS_BITMAP))
+ {
+ ASSERT(pBrush->hbmPattern);
+ GDIOBJ_SetOwnership(pBrush->hbmPattern, PsGetCurrentProcess());
+ NtGdiDeleteObject(pBrush->hbmPattern);
+ }
+
+ return TRUE;
+}
-HBRUSH FASTCALL
-IntGdiCreateBrushIndirect(PLOGBRUSH LogBrush)
+XLATEOBJ* FASTCALL
+IntGdiCreateBrushXlate(PDC Dc, GDIBRUSHOBJ *BrushObj, BOOLEAN *Failed)
{
+ XLATEOBJ *Result = NULL;
+
+ if (BrushObj->flAttrs & GDIBRUSH_IS_NULL)
+ {
+ Result = NULL;
+ *Failed = FALSE;
+ }
+ else if (BrushObj->flAttrs & GDIBRUSH_IS_SOLID)
+ {
+ Result = IntEngCreateXlate(0, PAL_RGB, Dc->w.hPalette, NULL);
+ *Failed = FALSE;
+ }
+ else
+ {
+ BITMAPOBJ *Pattern = BITMAPOBJ_LockBitmap(BrushObj->hbmPattern);
+ if (Pattern == NULL)
+ return NULL;
+
+ /* Special case: 1bpp pattern */
+ if (Pattern->SurfObj.iBitmapFormat == BMF_1BPP)
+ {
+ if (Dc->w.bitsPerPixel != 1)
+ Result = IntEngCreateSrcMonoXlate(Dc->w.hPalette, Dc->w.textColor, Dc->w.backgroundColor);
+ }
+ else if (BrushObj->flAttrs & GDIBRUSH_IS_DIB)
+ {
+ Result = IntEngCreateXlate(0, 0, Dc->w.hPalette, Pattern->hDIBPalette);
+ }
+
+ BITMAPOBJ_UnlockBitmap(Pattern);
+ *Failed = FALSE;
+ }
+
+ return Result;
+}
+
+VOID FASTCALL
+IntGdiInitBrushInstance(GDIBRUSHINST *BrushInst, PGDIBRUSHOBJ BrushObj, XLATEOBJ *XlateObj)
+{
+ ASSERT(BrushInst);
+ ASSERT(BrushObj);
+ if (BrushObj->flAttrs & GDIBRUSH_IS_NULL)
+ BrushInst->BrushObject.iSolidColor = 0;
+ else if (BrushObj->flAttrs & GDIBRUSH_IS_SOLID)
+ BrushInst->BrushObject.iSolidColor = XLATEOBJ_iXlate(XlateObj, BrushObj->BrushAttr.lbColor);
+ else
+ BrushInst->BrushObject.iSolidColor = 0xFFFFFFFF;
+ BrushInst->BrushObject.pvRbrush = BrushObj->ulRealization;
+ BrushInst->BrushObject.flColorType = 0;
+ BrushInst->GdiBrushObject = BrushObj;
+ BrushInst->XlateObject = XlateObj;
+}
+
+/**
+ * @name CalculateColorTableSize
+ *
+ * Internal routine to calculate the number of color table entries.
+ *
+ * @param BitmapInfoHeader
+ * Input bitmap information header, can be any version of
+ * BITMAPINFOHEADER or BITMAPCOREHEADER.
+ *
+ * @param ColorSpec
+ * Pointer to variable which specifiing the color mode (DIB_RGB_COLORS
+ * or DIB_RGB_COLORS). On successful return this value is normalized
+ * according to the bitmap info.
+ *
+ * @param ColorTableSize
+ * On successful return this variable is filled with number of
+ * entries in color table for the image with specified parameters.
+ *
+ * @return
+ * TRUE if the input values together form a valid image, FALSE otherwise.
+ */
+
+BOOL STDCALL
+CalculateColorTableSize(
+ CONST BITMAPINFOHEADER *BitmapInfoHeader,
+ UINT *ColorSpec,
+ UINT *ColorTableSize)
+{
+ WORD BitCount;
+ DWORD ClrUsed;
+ DWORD Compression;
+
+ /*
+ * At first get some basic parameters from the passed BitmapInfoHeader
+ * structure. It can have one of the following formats:
+ * - BITMAPCOREHEADER (the oldest one with totally different layout
+ * from the others)
+ * - BITMAPINFOHEADER (the standard and most common header)
+ * - BITMAPV4HEADER (extension of BITMAPINFOHEADER)
+ * - BITMAPV5HEADER (extension of BITMAPV4HEADER)
+ */
+
+ if (BitmapInfoHeader->biSize == sizeof(BITMAPCOREHEADER))
+ {
+ BitCount = ((LPBITMAPCOREHEADER)BitmapInfoHeader)->bcBitCount;
+ ClrUsed = 0;
+ Compression = BI_RGB;
+ }
+ else
+ {
+ BitCount = BitmapInfoHeader->biBitCount;
+ ClrUsed = BitmapInfoHeader->biClrUsed;
+ Compression = BitmapInfoHeader->biCompression;
+ }
+
+ switch (Compression)
+ {
+ case BI_BITFIELDS:
+ if (*ColorSpec == DIB_PAL_COLORS)
+ *ColorSpec = DIB_RGB_COLORS;
+
+ if (BitCount != 16 && BitCount != 32)
+ return FALSE;
+
+ /*
+ * For BITMAPV4HEADER/BITMAPV5HEADER the masks are included in
+ * the structure itself (bV4RedMask, bV4GreenMask, and bV4BlueMask).
+ * For BITMAPINFOHEADER the color masks are stored in the palette.
+ */
+
+ if (BitmapInfoHeader->biSize > sizeof(BITMAPINFOHEADER))
+ *ColorTableSize = 0;
+ else
+ *ColorTableSize = 3;
+
+ return TRUE;
+
+ case BI_RGB:
+ switch (BitCount)
+ {
+ case 1:
+ *ColorTableSize = ClrUsed ? min(ClrUsed, 2) : 2;
+ return TRUE;
+
+ case 4:
+ *ColorTableSize = ClrUsed ? min(ClrUsed, 16) : 16;
+ return TRUE;
+
+ case 8:
+ *ColorTableSize = ClrUsed ? min(ClrUsed, 256) : 256;
+ return TRUE;
+
+ default:
+ if (*ColorSpec == DIB_PAL_COLORS)
+ *ColorSpec = DIB_RGB_COLORS;
+ if (BitCount != 16 && BitCount != 24 && BitCount != 32)
+ return FALSE;
+ *ColorTableSize = ClrUsed;
+ return TRUE;
+ }
+
+ case BI_RLE4:
+ if (BitCount == 4)
+ {
+ *ColorTableSize = ClrUsed ? min(ClrUsed, 16) : 16;
+ return TRUE;
+ }
+ return FALSE;
+
+ case BI_RLE8:
+ if (BitCount == 8)
+ {
+ *ColorTableSize = ClrUsed ? min(ClrUsed, 256) : 256;
+ return TRUE;
+ }
+ return FALSE;
+
+ case BI_JPEG:
+ case BI_PNG:
+ *ColorTableSize = ClrUsed;
+ return TRUE;
+
+ default:
+ return FALSE;
+ }
+}
+
+HBRUSH STDCALL
+IntGdiCreateDIBBrush(
+ CONST BITMAPINFO *BitmapInfo,
+ UINT ColorSpec,
+ UINT BitmapInfoSize,
+ CONST VOID *PackedDIB)
+{
+ HBRUSH hBrush;
PGDIBRUSHOBJ BrushObject;
+ HBITMAP hPattern;
+ ULONG_PTR DataPtr;
+ UINT PaletteEntryCount;
+ PBITMAPOBJ BitmapObject;
+ INT PaletteType;
+
+ if (BitmapInfo->bmiHeader.biSize < sizeof(BITMAPINFOHEADER))
+ {
+ SetLastWin32Error(ERROR_INVALID_PARAMETER);
+ return NULL;
+ }
+
+ if (!CalculateColorTableSize(&BitmapInfo->bmiHeader, &ColorSpec,
+ &PaletteEntryCount))
+ {
+ SetLastWin32Error(ERROR_INVALID_PARAMETER);
+ return NULL;
+ }
+
+ DataPtr = (ULONG_PTR)BitmapInfo + BitmapInfo->bmiHeader.biSize;
+ if (ColorSpec == DIB_RGB_COLORS)
+ DataPtr += PaletteEntryCount * sizeof(RGBQUAD);
+ else
+ DataPtr += PaletteEntryCount * sizeof(USHORT);
+
+ hPattern = NtGdiCreateBitmap(BitmapInfo->bmiHeader.biWidth,
+ BitmapInfo->bmiHeader.biHeight,
+ BitmapInfo->bmiHeader.biPlanes,
+ BitmapInfo->bmiHeader.biBitCount,
+ (PVOID)DataPtr);
+ if (hPattern == NULL)
+ {
+ SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
+ return NULL;
+ }
+
+ BitmapObject = BITMAPOBJ_LockBitmap(hPattern);
+ ASSERT(BitmapObject != NULL);
+ BitmapObject->hDIBPalette = BuildDIBPalette(BitmapInfo, &PaletteType);
+ BITMAPOBJ_UnlockBitmap(BitmapObject);
+
+ hBrush = BRUSHOBJ_AllocBrush();
+ if (hBrush == NULL)
+ {
+ NtGdiDeleteObject(hPattern);
+ SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
+ return NULL;
+ }
+
+ BrushObject = BRUSHOBJ_LockBrush(hBrush);
+ ASSERT(BrushObject != NULL);
+
+ BrushObject->flAttrs |= GDIBRUSH_IS_BITMAP | GDIBRUSH_IS_DIB;
+ BrushObject->hbmPattern = hPattern;
+ /* FIXME: Fill in the rest of fields!!! */
+
+ GDIOBJ_SetOwnership(hPattern, NULL);
+
+ BRUSHOBJ_UnlockBrush(BrushObject);
+
+ return hBrush;
+}
+
+HBRUSH STDCALL
+IntGdiCreateHatchBrush(
+ INT Style,
+ COLORREF Color)
+{
HBRUSH hBrush;
-
+ PGDIBRUSHOBJ BrushObject;
+ HBITMAP hPattern;
+
+ if (Style < 0 || Style >= NB_HATCH_STYLES)
+ {
+ return 0;
+ }
+
+ hPattern = NtGdiCreateBitmap(8, 8, 1, 1, (LPBYTE)HatchBrushes[Style]);
+ if (hPattern == NULL)
+ {
+ SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
+ return NULL;
+ }
+
hBrush = BRUSHOBJ_AllocBrush();
if (hBrush == NULL)
{
+ NtGdiDeleteObject(hPattern);
SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
return NULL;
}
BrushObject = BRUSHOBJ_LockBrush(hBrush);
+ ASSERT(BrushObject != NULL);
- switch (LogBrush->lbStyle)
- {
- case BS_NULL:
- BrushObject->flAttrs = GDIBRUSH_IS_NULL;
- break;
-
- /* FIXME */
- case BS_HATCHED:
-
- case BS_SOLID:
- BrushObject->flAttrs = GDIBRUSH_IS_SOLID;
- BrushObject->BrushAttr.lbColor = LogBrush->lbColor & 0xFFFFFF;
- BrushObject->BrushObject.iSolidColor = BrushObject->BrushAttr.lbColor;
- /* FIXME: Fill in the rest of fields!!! */
- break;
-
- case BS_PATTERN:
- BrushObject->flAttrs = GDIBRUSH_IS_BITMAP;
- BrushObject->hbmPattern = BITMAPOBJ_CopyBitmap((HBITMAP)LogBrush->lbHatch);
- BrushObject->BrushObject.iSolidColor = 0xFFFFFFFF;
- /* FIXME: Fill in the rest of fields!!! */
- break;
+ BrushObject->flAttrs |= GDIBRUSH_IS_HATCH;
+ BrushObject->hbmPattern = hPattern;
+ BrushObject->BrushAttr.lbColor = Color & 0xFFFFFF;
- default:
- DPRINT1("Brush Style: %d\n", LogBrush->lbStyle);
- UNIMPLEMENTED;
+ GDIOBJ_SetOwnership(hPattern, NULL);
+
+ BRUSHOBJ_UnlockBrush(BrushObject);
+
+ return hBrush;
+}
+
+HBRUSH STDCALL
+IntGdiCreatePatternBrush(
+ HBITMAP hBitmap)
+{
+ HBRUSH hBrush;
+ PGDIBRUSHOBJ BrushObject;
+ HBITMAP hPattern;
+
+ hPattern = BITMAPOBJ_CopyBitmap(hBitmap);
+ if (hPattern == NULL)
+ {
+ SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
+ return NULL;
+ }
+
+ hBrush = BRUSHOBJ_AllocBrush();
+ if (hBrush == NULL)
+ {
+ NtGdiDeleteObject(hPattern);
+ SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
+ return NULL;
}
- BRUSHOBJ_UnlockBrush(hBrush);
+ BrushObject = BRUSHOBJ_LockBrush(hBrush);
+ ASSERT(BrushObject != NULL);
+
+ BrushObject->flAttrs |= GDIBRUSH_IS_BITMAP;
+ BrushObject->hbmPattern = hPattern;
+ /* FIXME: Fill in the rest of fields!!! */
+
+ GDIOBJ_SetOwnership(hPattern, NULL);
+
+ BRUSHOBJ_UnlockBrush(BrushObject);
+
+ return hBrush;
+}
+
+HBRUSH STDCALL
+IntGdiCreateSolidBrush(
+ COLORREF Color)
+{
+ HBRUSH hBrush;
+ PGDIBRUSHOBJ BrushObject;
+
+ hBrush = BRUSHOBJ_AllocBrush();
+ if (hBrush == NULL)
+ {
+ SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
+ return NULL;
+ }
+
+ BrushObject = BRUSHOBJ_LockBrush(hBrush);
+ ASSERT(BrushObject != NULL);
+
+ BrushObject->flAttrs |= GDIBRUSH_IS_SOLID;
+ BrushObject->BrushAttr.lbColor = Color & 0xFFFFFF;
+ /* FIXME: Fill in the rest of fields!!! */
+
+ BRUSHOBJ_UnlockBrush(BrushObject);
+
+ return hBrush;
+}
+
+HBRUSH STDCALL
+IntGdiCreateNullBrush(VOID)
+{
+ HBRUSH hBrush;
+ PGDIBRUSHOBJ BrushObject;
+
+ hBrush = BRUSHOBJ_AllocBrush();
+ if (hBrush == NULL)
+ {
+ SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
+ return NULL;
+ }
+
+ BrushObject = BRUSHOBJ_LockBrush(hBrush);
+ ASSERT(BrushObject != NULL);
+ BrushObject->flAttrs |= GDIBRUSH_IS_NULL;
+ BRUSHOBJ_UnlockBrush(BrushObject);
+
return hBrush;
}
PGDIBRUSHOBJ BrushObj)
{
RECTL DestRect;
- SURFOBJ *SurfObj;
- BOOL ret;
+ BITMAPOBJ *BitmapObj;
+ GDIBRUSHINST BrushInst;
+ POINTL BrushOrigin;
+ BOOL ret = TRUE;
- SurfObj = (SURFOBJ *)AccessUserObject((ULONG)dc->Surface);
- if (SurfObj == NULL)
+ ASSERT(BrushObj);
+
+ BitmapObj = BITMAPOBJ_LockBitmap(dc->w.hBitmap);
+ if (BitmapObj == NULL)
{
SetLastWin32Error(ERROR_INVALID_HANDLE);
return FALSE;
}
- ASSERT(BrushObj);
if (!(BrushObj->flAttrs & GDIBRUSH_IS_NULL))
{
if (Width > 0)
DestRect.bottom = YLeft + dc->w.DCOrgY + 1;
}
+ IntLPtoDP(dc, (LPPOINT)&DestRect, 2);
+
+ BrushOrigin.x = BrushObj->ptOrigin.x + dc->w.DCOrgX;
+ BrushOrigin.y = BrushObj->ptOrigin.y + dc->w.DCOrgY;
+
+ IntGdiInitBrushInstance(&BrushInst, BrushObj, dc->XlateBrush);
+
ret = IntEngBitBlt(
- SurfObj,
+ &BitmapObj->SurfObj,
NULL,
NULL,
dc->CombinedClip,
&DestRect,
NULL,
NULL,
- &BrushObj->BrushObject,
- NULL,
- ROP);
+ &BrushInst.BrushObject,
+ &BrushOrigin,
+ ROP3_TO_ROP4(ROP));
}
+ BITMAPOBJ_UnlockBitmap(BitmapObj);
+
return ret;
}
PPATRECT r;
PGDIBRUSHOBJ BrushObj;
DC *dc;
-
+
dc = DC_LockDc(hDC);
if (dc == NULL)
{
SetLastWin32Error(ERROR_INVALID_HANDLE);
return FALSE;
}
-
+ if (dc->IsIC)
+ {
+ DC_UnlockDc(dc);
+ /* Yes, Windows really returns TRUE in this case */
+ return TRUE;
+ }
+
for (r = pRects, i = 0; i < cRects; i++)
{
BrushObj = BRUSHOBJ_LockBrush(r->hBrush);
- IntPatBlt(
- dc,
- r->r.left,
- r->r.top,
- r->r.right,
- r->r.bottom,
- dwRop,
- BrushObj);
- BRUSHOBJ_UnlockBrush(r->hBrush);
+ if(BrushObj != NULL)
+ {
+ IntPatBlt(
+ dc,
+ r->r.left,
+ r->r.top,
+ r->r.right,
+ r->r.bottom,
+ dwRop,
+ BrushObj);
+ BRUSHOBJ_UnlockBrush(BrushObj);
+ }
r++;
}
- DC_UnlockDc( hDC );
-
+ DC_UnlockDc(dc);
+
return TRUE;
}
/* PUBLIC FUNCTIONS ***********************************************************/
HBRUSH STDCALL
-NtGdiCreateBrushIndirect(CONST LOGBRUSH *LogBrush)
+NtGdiCreateDIBBrush(
+ IN PVOID BitmapInfoAndData,
+ IN FLONG ColorSpec,
+ IN UINT BitmapInfoSize,
+ IN BOOL b8X8,
+ IN BOOL bPen,
+ IN PVOID PackedDIB)
{
- LOGBRUSH SafeLogBrush;
- NTSTATUS Status;
-
- Status = MmCopyFromCaller(&SafeLogBrush, LogBrush, sizeof(LOGBRUSH));
+ BITMAPINFO *SafeBitmapInfoAndData;
+ NTSTATUS Status = STATUS_SUCCESS;
+ HBRUSH hBrush;
+
+ SafeBitmapInfoAndData = EngAllocMem(0, BitmapInfoSize, 0);
+ if (SafeBitmapInfoAndData == NULL)
+ {
+ SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
+ return NULL;
+ }
+
+ _SEH_TRY
+ {
+ ProbeForRead(BitmapInfoAndData,
+ BitmapInfoSize,
+ 1);
+ RtlCopyMemory(SafeBitmapInfoAndData,
+ BitmapInfoAndData,
+ BitmapInfoSize);
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+
if (!NT_SUCCESS(Status))
{
+ EngFreeMem(SafeBitmapInfoAndData);
SetLastNtError(Status);
return 0;
}
-
- return IntGdiCreateBrushIndirect(&SafeLogBrush);
-}
-
-HBRUSH STDCALL
-NtGdiCreateDIBPatternBrush(HGLOBAL hDIBPacked, UINT ColorSpec)
-{
- UNIMPLEMENTED;
- return 0;
-}
-
-HBRUSH STDCALL
-NtGdiCreateDIBPatternBrushPt(CONST VOID *PackedDIB, UINT Usage)
-{
- UNIMPLEMENTED;
- return 0;
-}
-
-HBRUSH STDCALL
-NtGdiCreateHatchBrush(INT Style, COLORREF Color)
-{
- LOGBRUSH LogBrush;
- if (Style < 0 || Style >= NB_HATCH_STYLES)
- return 0;
+ hBrush = IntGdiCreateDIBBrush(SafeBitmapInfoAndData, ColorSpec,
+ BitmapInfoSize, PackedDIB);
- LogBrush.lbStyle = BS_HATCHED;
- LogBrush.lbColor = Color;
- LogBrush.lbHatch = Style;
+ EngFreeMem(SafeBitmapInfoAndData);
- return IntGdiCreateBrushIndirect(&LogBrush);
+ return hBrush;
}
HBRUSH STDCALL
-NtGdiCreatePatternBrush(HBITMAP hBitmap)
+NtGdiCreateHatchBrush(
+ INT Style,
+ COLORREF Color)
{
- LOGBRUSH LogBrush;
-
- LogBrush.lbStyle = BS_PATTERN;
- LogBrush.lbColor = 0;
- LogBrush.lbHatch = (ULONG)hBitmap;
-
- return IntGdiCreateBrushIndirect(&LogBrush);
+ return IntGdiCreateHatchBrush(Style, Color);
}
HBRUSH STDCALL
-NtGdiCreateSolidBrush(COLORREF Color)
+NtGdiCreatePatternBrush(
+ HBITMAP hBitmap)
{
- LOGBRUSH LogBrush;
-
- LogBrush.lbStyle = BS_SOLID;
- LogBrush.lbColor = Color;
- LogBrush.lbHatch = 0;
-
- return IntGdiCreateBrushIndirect(&LogBrush);
+ return IntGdiCreatePatternBrush(hBitmap);
}
-BOOL STDCALL
-NtGdiFixBrushOrgEx(VOID)
+HBRUSH STDCALL
+NtGdiCreateSolidBrush(COLORREF Color,
+ IN OPTIONAL HBRUSH hbr)
{
- return FALSE;
+ return IntGdiCreateSolidBrush(Color);
}
/*
* NtGdiSetBrushOrgEx
*
* The NtGdiSetBrushOrgEx function sets the brush origin that GDI assigns to
- * the next brush an application selects into the specified device context.
+ * the next brush an application selects into the specified device context.
*
* Status
* @implemented
if (Point != NULL)
{
+ NTSTATUS Status = STATUS_SUCCESS;
POINT SafePoint;
SafePoint.x = dc->w.brushOrgX;
SafePoint.y = dc->w.brushOrgY;
- MmCopyToCaller(Point, &SafePoint, sizeof(POINT));
+ _SEH_TRY
+ {
+ ProbeForWrite(Point,
+ sizeof(POINT),
+ 1);
+ *Point = SafePoint;
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+
+ if(!NT_SUCCESS(Status))
+ {
+ DC_UnlockDc(dc);
+ SetLastNtError(Status);
+ return FALSE;
+ }
}
dc->w.brushOrgX = XOrg;
dc->w.brushOrgY = YOrg;
- DC_UnlockDc(hDC);
+ DC_UnlockDc(dc);
return TRUE;
}
NtGdiPolyPatBlt(
HDC hDC,
DWORD dwRop,
- PPATRECT pRects,
- INT cRects,
- ULONG Reserved)
+ IN PPOLYPATBLT pRects,
+ IN DWORD cRects,
+ IN DWORD Mode)
{
- PPATRECT rb;
- NTSTATUS Status;
+ PPATRECT rb = NULL;
+ NTSTATUS Status = STATUS_SUCCESS;
BOOL Ret;
-
+
if (cRects > 0)
{
rb = ExAllocatePoolWithTag(PagedPool, sizeof(PATRECT) * cRects, TAG_PATBLT);
SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
return FALSE;
}
- Status = MmCopyFromCaller(rb, pRects, sizeof(PATRECT) * cRects);
+ _SEH_TRY
+ {
+ ProbeForRead(pRects,
+ cRects * sizeof(PATRECT),
+ 1);
+ RtlCopyMemory(rb,
+ pRects,
+ cRects * sizeof(PATRECT));
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+
if (!NT_SUCCESS(Status))
{
ExFreePool(rb);
return FALSE;
}
}
-
- Ret = IntGdiPolyPatBlt(hDC, dwRop, pRects, cRects, Reserved);
-
+
+ Ret = IntGdiPolyPatBlt(hDC, dwRop, (PPATRECT)pRects, cRects, Mode);
+
if (cRects > 0)
ExFreePool(rb);
SetLastWin32Error(ERROR_INVALID_HANDLE);
return FALSE;
}
+ if (dc->IsIC)
+ {
+ DC_UnlockDc(dc);
+ /* Yes, Windows really returns TRUE in this case */
+ return TRUE;
+ }
BrushObj = BRUSHOBJ_LockBrush(dc->w.hBrush);
if (BrushObj == NULL)
{
SetLastWin32Error(ERROR_INVALID_HANDLE);
- DC_UnlockDc(hDC);
+ DC_UnlockDc(dc);
return FALSE;
}
ROP,
BrushObj);
- BRUSHOBJ_UnlockBrush(dc->w.hBrush);
- DC_UnlockDc(hDC);
+ BRUSHOBJ_UnlockBrush(BrushObj);
+ DC_UnlockDc(dc);
return ret;
}