- Fix KiDispatchException to unmask KI_EXCEPTION_INTERNAL when setting the exception...
[reactos.git] / reactos / subsystems / win32 / win32k / objects / brush.c
1 /*
2 * ReactOS Win32 Subsystem
3 *
4 * Copyright (C) 1998 - 2004 ReactOS Team
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 *
20 * $Id$
21 */
22
23 #include <w32k.h>
24
25 #define NDEBUG
26 #include <debug.h>
27
28 static const USHORT HatchBrushes[NB_HATCH_STYLES][8] =
29 {
30 {0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00}, /* HS_HORIZONTAL */
31 {0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08}, /* HS_VERTICAL */
32 {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80}, /* HS_FDIAGONAL */
33 {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01}, /* HS_BDIAGONAL */
34 {0x08, 0x08, 0x08, 0xff, 0x08, 0x08, 0x08, 0x08}, /* HS_CROSS */
35 {0x81, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x81} /* HS_DIAGCROSS */
36 };
37
38 BOOL INTERNAL_CALL
39 BRUSH_Cleanup(PVOID ObjectBody)
40 {
41 PGDIBRUSHOBJ pBrush = (PGDIBRUSHOBJ)ObjectBody;
42 if(pBrush->flAttrs & (GDIBRUSH_IS_HATCH | GDIBRUSH_IS_BITMAP))
43 {
44 ASSERT(pBrush->hbmPattern);
45 GDIOBJ_SetOwnership(GdiHandleTable, pBrush->hbmPattern, PsGetCurrentProcess());
46 NtGdiDeleteObject(pBrush->hbmPattern);
47 }
48
49 return TRUE;
50 }
51
52 INT FASTCALL
53 BRUSH_GetObject (PGDIBRUSHOBJ BrushObject, INT Count, LPLOGBRUSH Buffer)
54 {
55 if( Buffer == NULL ) return sizeof(BRUSHOBJ);
56 if (Count < sizeof(BRUSHOBJ)) return 0;
57 if (Count > sizeof(BRUSHOBJ)) Count = sizeof(BRUSHOBJ);
58
59 /* Set colour */
60 Buffer->lbColor = BrushObject->BrushAttr.lbColor;
61
62 /* set Hatch */
63 if ((BrushObject->flAttrs & GDIBRUSH_IS_HATCH)!=0)
64 {
65 /* FIXME : is this right value */
66 Buffer->lbHatch = (LONG)BrushObject->hbmPattern;
67 }
68 else
69 {
70 Buffer->lbHatch = 0;
71 }
72
73 Buffer->lbStyle = 0;
74
75 /* Get the type of style */
76 if ((BrushObject->flAttrs & GDIBRUSH_IS_SOLID)!=0)
77 {
78 Buffer->lbStyle = BS_SOLID;
79 }
80 else if ((BrushObject->flAttrs & GDIBRUSH_IS_NULL)!=0)
81 {
82 Buffer->lbStyle = BS_NULL; // BS_HOLLOW
83 }
84 else if ((BrushObject->flAttrs & GDIBRUSH_IS_HATCH)!=0)
85 {
86 Buffer->lbStyle = BS_HATCHED;
87 }
88 else if ((BrushObject->flAttrs & GDIBRUSH_IS_BITMAP)!=0)
89 {
90 Buffer->lbStyle = BS_PATTERN;
91 }
92 else if ((BrushObject->flAttrs & GDIBRUSH_IS_DIB)!=0)
93 {
94 Buffer->lbStyle = BS_DIBPATTERN;
95 }
96
97 /* FIXME
98 else if ((BrushObject->flAttrs & )!=0)
99 {
100 Buffer->lbStyle = BS_INDEXED;
101 }
102 else if ((BrushObject->flAttrs & )!=0)
103 {
104 Buffer->lbStyle = BS_DIBPATTERNPT;
105 }
106 */
107
108 /* FIXME */
109 return sizeof(BRUSHOBJ);
110 }
111
112
113 XLATEOBJ* FASTCALL
114 IntGdiCreateBrushXlate(PDC Dc, GDIBRUSHOBJ *BrushObj, BOOLEAN *Failed)
115 {
116 XLATEOBJ *Result = NULL;
117
118 if (BrushObj->flAttrs & GDIBRUSH_IS_NULL)
119 {
120 Result = NULL;
121 *Failed = FALSE;
122 }
123 else if (BrushObj->flAttrs & GDIBRUSH_IS_SOLID)
124 {
125 Result = IntEngCreateXlate(0, PAL_RGB, Dc->w.hPalette, NULL);
126 *Failed = FALSE;
127 }
128 else
129 {
130 BITMAPOBJ *Pattern = BITMAPOBJ_LockBitmap(BrushObj->hbmPattern);
131 if (Pattern == NULL)
132 return NULL;
133
134 /* Special case: 1bpp pattern */
135 if (Pattern->SurfObj.iBitmapFormat == BMF_1BPP)
136 {
137 if (Dc->w.bitsPerPixel != 1)
138 Result = IntEngCreateSrcMonoXlate(Dc->w.hPalette, Dc->w.textColor, Dc->w.backgroundColor);
139 }
140 else if (BrushObj->flAttrs & GDIBRUSH_IS_DIB)
141 {
142 Result = IntEngCreateXlate(0, 0, Dc->w.hPalette, Pattern->hDIBPalette);
143 }
144
145 BITMAPOBJ_UnlockBitmap(Pattern);
146 *Failed = FALSE;
147 }
148
149 return Result;
150 }
151
152 VOID FASTCALL
153 IntGdiInitBrushInstance(GDIBRUSHINST *BrushInst, PGDIBRUSHOBJ BrushObj, XLATEOBJ *XlateObj)
154 {
155 ASSERT(BrushInst);
156 ASSERT(BrushObj);
157 if (BrushObj->flAttrs & GDIBRUSH_IS_NULL)
158 BrushInst->BrushObject.iSolidColor = 0;
159 else if (BrushObj->flAttrs & GDIBRUSH_IS_SOLID)
160 BrushInst->BrushObject.iSolidColor = XLATEOBJ_iXlate(XlateObj, BrushObj->BrushAttr.lbColor);
161 else
162 BrushInst->BrushObject.iSolidColor = 0xFFFFFFFF;
163 BrushInst->BrushObject.pvRbrush = BrushObj->ulRealization;
164 BrushInst->BrushObject.flColorType = 0;
165 BrushInst->GdiBrushObject = BrushObj;
166 BrushInst->XlateObject = XlateObj;
167 }
168
169 /**
170 * @name CalculateColorTableSize
171 *
172 * Internal routine to calculate the number of color table entries.
173 *
174 * @param BitmapInfoHeader
175 * Input bitmap information header, can be any version of
176 * BITMAPINFOHEADER or BITMAPCOREHEADER.
177 *
178 * @param ColorSpec
179 * Pointer to variable which specifiing the color mode (DIB_RGB_COLORS
180 * or DIB_RGB_COLORS). On successful return this value is normalized
181 * according to the bitmap info.
182 *
183 * @param ColorTableSize
184 * On successful return this variable is filled with number of
185 * entries in color table for the image with specified parameters.
186 *
187 * @return
188 * TRUE if the input values together form a valid image, FALSE otherwise.
189 */
190
191 BOOL STDCALL
192 CalculateColorTableSize(
193 CONST BITMAPINFOHEADER *BitmapInfoHeader,
194 UINT *ColorSpec,
195 UINT *ColorTableSize)
196 {
197 WORD BitCount;
198 DWORD ClrUsed;
199 DWORD Compression;
200
201 /*
202 * At first get some basic parameters from the passed BitmapInfoHeader
203 * structure. It can have one of the following formats:
204 * - BITMAPCOREHEADER (the oldest one with totally different layout
205 * from the others)
206 * - BITMAPINFOHEADER (the standard and most common header)
207 * - BITMAPV4HEADER (extension of BITMAPINFOHEADER)
208 * - BITMAPV5HEADER (extension of BITMAPV4HEADER)
209 */
210
211 if (BitmapInfoHeader->biSize == sizeof(BITMAPCOREHEADER))
212 {
213 BitCount = ((LPBITMAPCOREHEADER)BitmapInfoHeader)->bcBitCount;
214 ClrUsed = 0;
215 Compression = BI_RGB;
216 }
217 else
218 {
219 BitCount = BitmapInfoHeader->biBitCount;
220 ClrUsed = BitmapInfoHeader->biClrUsed;
221 Compression = BitmapInfoHeader->biCompression;
222 }
223
224 switch (Compression)
225 {
226 case BI_BITFIELDS:
227 if (*ColorSpec == DIB_PAL_COLORS)
228 *ColorSpec = DIB_RGB_COLORS;
229
230 if (BitCount != 16 && BitCount != 32)
231 return FALSE;
232
233 /*
234 * For BITMAPV4HEADER/BITMAPV5HEADER the masks are included in
235 * the structure itself (bV4RedMask, bV4GreenMask, and bV4BlueMask).
236 * For BITMAPINFOHEADER the color masks are stored in the palette.
237 */
238
239 if (BitmapInfoHeader->biSize > sizeof(BITMAPINFOHEADER))
240 *ColorTableSize = 0;
241 else
242 *ColorTableSize = 3;
243
244 return TRUE;
245
246 case BI_RGB:
247 switch (BitCount)
248 {
249 case 1:
250 *ColorTableSize = ClrUsed ? min(ClrUsed, 2) : 2;
251 return TRUE;
252
253 case 4:
254 *ColorTableSize = ClrUsed ? min(ClrUsed, 16) : 16;
255 return TRUE;
256
257 case 8:
258 *ColorTableSize = ClrUsed ? min(ClrUsed, 256) : 256;
259 return TRUE;
260
261 default:
262 if (*ColorSpec == DIB_PAL_COLORS)
263 *ColorSpec = DIB_RGB_COLORS;
264 if (BitCount != 16 && BitCount != 24 && BitCount != 32)
265 return FALSE;
266 *ColorTableSize = ClrUsed;
267 return TRUE;
268 }
269
270 case BI_RLE4:
271 if (BitCount == 4)
272 {
273 *ColorTableSize = ClrUsed ? min(ClrUsed, 16) : 16;
274 return TRUE;
275 }
276 return FALSE;
277
278 case BI_RLE8:
279 if (BitCount == 8)
280 {
281 *ColorTableSize = ClrUsed ? min(ClrUsed, 256) : 256;
282 return TRUE;
283 }
284 return FALSE;
285
286 case BI_JPEG:
287 case BI_PNG:
288 *ColorTableSize = ClrUsed;
289 return TRUE;
290
291 default:
292 return FALSE;
293 }
294 }
295
296 HBRUSH STDCALL
297 IntGdiCreateDIBBrush(
298 CONST BITMAPINFO *BitmapInfo,
299 UINT ColorSpec,
300 UINT BitmapInfoSize,
301 CONST VOID *PackedDIB)
302 {
303 HBRUSH hBrush;
304 PGDIBRUSHOBJ BrushObject;
305 HBITMAP hPattern;
306 ULONG_PTR DataPtr;
307 UINT PaletteEntryCount;
308 PBITMAPOBJ BitmapObject;
309 INT PaletteType;
310
311 if (BitmapInfo->bmiHeader.biSize < sizeof(BITMAPINFOHEADER))
312 {
313 SetLastWin32Error(ERROR_INVALID_PARAMETER);
314 return NULL;
315 }
316
317 if (!CalculateColorTableSize(&BitmapInfo->bmiHeader, &ColorSpec,
318 &PaletteEntryCount))
319 {
320 SetLastWin32Error(ERROR_INVALID_PARAMETER);
321 return NULL;
322 }
323
324 DataPtr = (ULONG_PTR)BitmapInfo + BitmapInfo->bmiHeader.biSize;
325 if (ColorSpec == DIB_RGB_COLORS)
326 DataPtr += PaletteEntryCount * sizeof(RGBQUAD);
327 else
328 DataPtr += PaletteEntryCount * sizeof(USHORT);
329
330 hPattern = NtGdiCreateBitmap(BitmapInfo->bmiHeader.biWidth,
331 BitmapInfo->bmiHeader.biHeight,
332 BitmapInfo->bmiHeader.biPlanes,
333 BitmapInfo->bmiHeader.biBitCount,
334 (PVOID)DataPtr);
335 if (hPattern == NULL)
336 {
337 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
338 return NULL;
339 }
340
341 BitmapObject = BITMAPOBJ_LockBitmap(hPattern);
342 ASSERT(BitmapObject != NULL);
343 BitmapObject->hDIBPalette = BuildDIBPalette(BitmapInfo, &PaletteType);
344 BITMAPOBJ_UnlockBitmap(BitmapObject);
345
346 hBrush = BRUSHOBJ_AllocBrush();
347 if (hBrush == NULL)
348 {
349 NtGdiDeleteObject(hPattern);
350 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
351 return NULL;
352 }
353
354 BrushObject = BRUSHOBJ_LockBrush(hBrush);
355 ASSERT(BrushObject != NULL);
356
357 BrushObject->flAttrs |= GDIBRUSH_IS_BITMAP | GDIBRUSH_IS_DIB;
358 BrushObject->hbmPattern = hPattern;
359 /* FIXME: Fill in the rest of fields!!! */
360
361 GDIOBJ_SetOwnership(GdiHandleTable, hPattern, NULL);
362
363 BRUSHOBJ_UnlockBrush(BrushObject);
364
365 return hBrush;
366 }
367
368 HBRUSH STDCALL
369 IntGdiCreateHatchBrush(
370 INT Style,
371 COLORREF Color)
372 {
373 HBRUSH hBrush;
374 PGDIBRUSHOBJ BrushObject;
375 HBITMAP hPattern;
376
377 if (Style < 0 || Style >= NB_HATCH_STYLES)
378 {
379 return 0;
380 }
381
382 hPattern = NtGdiCreateBitmap(8, 8, 1, 1, (LPBYTE)HatchBrushes[Style]);
383 if (hPattern == NULL)
384 {
385 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
386 return NULL;
387 }
388
389 hBrush = BRUSHOBJ_AllocBrush();
390 if (hBrush == NULL)
391 {
392 NtGdiDeleteObject(hPattern);
393 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
394 return NULL;
395 }
396
397 BrushObject = BRUSHOBJ_LockBrush(hBrush);
398 ASSERT(BrushObject != NULL);
399
400 BrushObject->flAttrs |= GDIBRUSH_IS_HATCH;
401 BrushObject->hbmPattern = hPattern;
402 BrushObject->BrushAttr.lbColor = Color & 0xFFFFFF;
403
404 GDIOBJ_SetOwnership(GdiHandleTable, hPattern, NULL);
405
406 BRUSHOBJ_UnlockBrush(BrushObject);
407
408 return hBrush;
409 }
410
411 HBRUSH STDCALL
412 IntGdiCreatePatternBrush(
413 HBITMAP hBitmap)
414 {
415 HBRUSH hBrush;
416 PGDIBRUSHOBJ BrushObject;
417 HBITMAP hPattern;
418
419 hPattern = BITMAPOBJ_CopyBitmap(hBitmap);
420 if (hPattern == NULL)
421 {
422 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
423 return NULL;
424 }
425
426 hBrush = BRUSHOBJ_AllocBrush();
427 if (hBrush == NULL)
428 {
429 NtGdiDeleteObject(hPattern);
430 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
431 return NULL;
432 }
433
434 BrushObject = BRUSHOBJ_LockBrush(hBrush);
435 ASSERT(BrushObject != NULL);
436
437 BrushObject->flAttrs |= GDIBRUSH_IS_BITMAP;
438 BrushObject->hbmPattern = hPattern;
439 /* FIXME: Fill in the rest of fields!!! */
440
441 GDIOBJ_SetOwnership(GdiHandleTable, hPattern, NULL);
442
443 BRUSHOBJ_UnlockBrush(BrushObject);
444
445 return hBrush;
446 }
447
448 HBRUSH STDCALL
449 IntGdiCreateSolidBrush(
450 COLORREF Color)
451 {
452 HBRUSH hBrush;
453 PGDIBRUSHOBJ BrushObject;
454
455 hBrush = BRUSHOBJ_AllocBrush();
456 if (hBrush == NULL)
457 {
458 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
459 return NULL;
460 }
461
462 BrushObject = BRUSHOBJ_LockBrush(hBrush);
463 ASSERT(BrushObject != NULL);
464
465 BrushObject->flAttrs |= GDIBRUSH_IS_SOLID;
466
467 BrushObject->BrushAttr.lbColor = Color;
468 /* FIXME: Fill in the rest of fields!!! */
469
470 BRUSHOBJ_UnlockBrush(BrushObject);
471
472 return hBrush;
473 }
474
475 HBRUSH STDCALL
476 IntGdiCreateNullBrush(VOID)
477 {
478 HBRUSH hBrush;
479 PGDIBRUSHOBJ BrushObject;
480
481 hBrush = BRUSHOBJ_AllocBrush();
482 if (hBrush == NULL)
483 {
484 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
485 return NULL;
486 }
487
488 BrushObject = BRUSHOBJ_LockBrush(hBrush);
489 ASSERT(BrushObject != NULL);
490 BrushObject->flAttrs |= GDIBRUSH_IS_NULL;
491 BRUSHOBJ_UnlockBrush(BrushObject);
492
493 return hBrush;
494 }
495
496 BOOL FASTCALL
497 IntPatBlt(
498 PDC dc,
499 INT XLeft,
500 INT YLeft,
501 INT Width,
502 INT Height,
503 DWORD ROP,
504 PGDIBRUSHOBJ BrushObj)
505 {
506 RECTL DestRect;
507 BITMAPOBJ *BitmapObj;
508 GDIBRUSHINST BrushInst;
509 POINTL BrushOrigin;
510 BOOL ret = TRUE;
511
512 ASSERT(BrushObj);
513
514 BitmapObj = BITMAPOBJ_LockBitmap(dc->w.hBitmap);
515 if (BitmapObj == NULL)
516 {
517 SetLastWin32Error(ERROR_INVALID_HANDLE);
518 return FALSE;
519 }
520
521 if (!(BrushObj->flAttrs & GDIBRUSH_IS_NULL))
522 {
523 if (Width > 0)
524 {
525 DestRect.left = XLeft + dc->w.DCOrgX;
526 DestRect.right = XLeft + Width + dc->w.DCOrgX;
527 }
528 else
529 {
530 DestRect.left = XLeft + Width + 1 + dc->w.DCOrgX;
531 DestRect.right = XLeft + dc->w.DCOrgX + 1;
532 }
533
534 if (Height > 0)
535 {
536 DestRect.top = YLeft + dc->w.DCOrgY;
537 DestRect.bottom = YLeft + Height + dc->w.DCOrgY;
538 }
539 else
540 {
541 DestRect.top = YLeft + Height + dc->w.DCOrgY + 1;
542 DestRect.bottom = YLeft + dc->w.DCOrgY + 1;
543 }
544
545 IntLPtoDP(dc, (LPPOINT)&DestRect, 2);
546
547 BrushOrigin.x = BrushObj->ptOrigin.x + dc->w.DCOrgX;
548 BrushOrigin.y = BrushObj->ptOrigin.y + dc->w.DCOrgY;
549
550 IntGdiInitBrushInstance(&BrushInst, BrushObj, dc->XlateBrush);
551
552 ret = IntEngBitBlt(
553 &BitmapObj->SurfObj,
554 NULL,
555 NULL,
556 dc->CombinedClip,
557 NULL,
558 &DestRect,
559 NULL,
560 NULL,
561 &BrushInst.BrushObject,
562 &BrushOrigin,
563 ROP3_TO_ROP4(ROP));
564 }
565
566 BITMAPOBJ_UnlockBitmap(BitmapObj);
567
568 return ret;
569 }
570
571 BOOL FASTCALL
572 IntGdiPolyPatBlt(
573 HDC hDC,
574 DWORD dwRop,
575 PPATRECT pRects,
576 int cRects,
577 ULONG Reserved)
578 {
579 int i;
580 PPATRECT r;
581 PGDIBRUSHOBJ BrushObj;
582 DC *dc;
583
584 dc = DC_LockDc(hDC);
585 if (dc == NULL)
586 {
587 SetLastWin32Error(ERROR_INVALID_HANDLE);
588 return FALSE;
589 }
590 if (dc->IsIC)
591 {
592 DC_UnlockDc(dc);
593 /* Yes, Windows really returns TRUE in this case */
594 return TRUE;
595 }
596
597 for (r = pRects, i = 0; i < cRects; i++)
598 {
599 BrushObj = BRUSHOBJ_LockBrush(r->hBrush);
600 if(BrushObj != NULL)
601 {
602 IntPatBlt(
603 dc,
604 r->r.left,
605 r->r.top,
606 r->r.right,
607 r->r.bottom,
608 dwRop,
609 BrushObj);
610 BRUSHOBJ_UnlockBrush(BrushObj);
611 }
612 r++;
613 }
614
615 DC_UnlockDc(dc);
616
617 return TRUE;
618 }
619
620 /* PUBLIC FUNCTIONS ***********************************************************/
621
622 HBRUSH STDCALL
623 NtGdiCreateDIBBrush(
624 IN PVOID BitmapInfoAndData,
625 IN FLONG ColorSpec,
626 IN UINT BitmapInfoSize,
627 IN BOOL b8X8,
628 IN BOOL bPen,
629 IN PVOID PackedDIB)
630 {
631 BITMAPINFO *SafeBitmapInfoAndData;
632 NTSTATUS Status = STATUS_SUCCESS;
633 HBRUSH hBrush;
634
635 SafeBitmapInfoAndData = EngAllocMem(0, BitmapInfoSize, 0);
636 if (SafeBitmapInfoAndData == NULL)
637 {
638 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
639 return NULL;
640 }
641
642 _SEH_TRY
643 {
644 ProbeForRead(BitmapInfoAndData,
645 BitmapInfoSize,
646 1);
647 RtlCopyMemory(SafeBitmapInfoAndData,
648 BitmapInfoAndData,
649 BitmapInfoSize);
650 }
651 _SEH_HANDLE
652 {
653 Status = _SEH_GetExceptionCode();
654 }
655 _SEH_END;
656
657 if (!NT_SUCCESS(Status))
658 {
659 EngFreeMem(SafeBitmapInfoAndData);
660 SetLastNtError(Status);
661 return 0;
662 }
663
664 hBrush = IntGdiCreateDIBBrush(SafeBitmapInfoAndData, ColorSpec,
665 BitmapInfoSize, PackedDIB);
666
667 EngFreeMem(SafeBitmapInfoAndData);
668
669 return hBrush;
670 }
671
672 HBRUSH STDCALL
673 NtGdiCreateHatchBrushInternal(
674 ULONG Style,
675 COLORREF Color,
676 BOOL bPen)
677 {
678 return IntGdiCreateHatchBrush(Style, Color);
679 }
680
681 HBRUSH STDCALL
682 NtGdiCreatePatternBrushInternal(
683 HBITMAP hBitmap,
684 BOOL bPen,
685 BOOL b8x8)
686 {
687 return IntGdiCreatePatternBrush(hBitmap);
688 }
689
690 HBRUSH STDCALL
691 NtGdiCreateSolidBrush(COLORREF Color,
692 IN OPTIONAL HBRUSH hbr)
693 {
694 return IntGdiCreateSolidBrush(Color);
695 }
696
697 /*
698 * NtGdiSetBrushOrgEx
699 *
700 * The NtGdiSetBrushOrgEx function sets the brush origin that GDI assigns to
701 * the next brush an application selects into the specified device context.
702 *
703 * Status
704 * @implemented
705 */
706
707 BOOL STDCALL
708 NtGdiSetBrushOrgEx(HDC hDC, INT XOrg, INT YOrg, LPPOINT Point)
709 {
710 PDC dc = DC_LockDc(hDC);
711 if (dc == NULL)
712 {
713 SetLastWin32Error(ERROR_INVALID_HANDLE);
714 return FALSE;
715 }
716
717 if (Point != NULL)
718 {
719 NTSTATUS Status = STATUS_SUCCESS;
720 POINT SafePoint;
721 SafePoint.x = dc->w.brushOrgX;
722 SafePoint.y = dc->w.brushOrgY;
723 _SEH_TRY
724 {
725 ProbeForWrite(Point,
726 sizeof(POINT),
727 1);
728 *Point = SafePoint;
729 }
730 _SEH_HANDLE
731 {
732 Status = _SEH_GetExceptionCode();
733 }
734 _SEH_END;
735
736 if(!NT_SUCCESS(Status))
737 {
738 DC_UnlockDc(dc);
739 SetLastNtError(Status);
740 return FALSE;
741 }
742 }
743
744 dc->w.brushOrgX = XOrg;
745 dc->w.brushOrgY = YOrg;
746 DC_UnlockDc(dc);
747
748 return TRUE;
749 }
750
751 BOOL STDCALL
752 NtGdiPolyPatBlt(
753 HDC hDC,
754 DWORD dwRop,
755 IN PPOLYPATBLT pRects,
756 IN DWORD cRects,
757 IN DWORD Mode)
758 {
759 PPATRECT rb = NULL;
760 NTSTATUS Status = STATUS_SUCCESS;
761 BOOL Ret;
762
763 if (cRects > 0)
764 {
765 rb = ExAllocatePoolWithTag(PagedPool, sizeof(PATRECT) * cRects, TAG_PATBLT);
766 if (!rb)
767 {
768 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
769 return FALSE;
770 }
771 _SEH_TRY
772 {
773 ProbeForRead(pRects,
774 cRects * sizeof(PATRECT),
775 1);
776 RtlCopyMemory(rb,
777 pRects,
778 cRects * sizeof(PATRECT));
779 }
780 _SEH_HANDLE
781 {
782 Status = _SEH_GetExceptionCode();
783 }
784 _SEH_END;
785
786 if (!NT_SUCCESS(Status))
787 {
788 ExFreePool(rb);
789 SetLastNtError(Status);
790 return FALSE;
791 }
792 }
793
794 Ret = IntGdiPolyPatBlt(hDC, dwRop, (PPATRECT)pRects, cRects, Mode);
795
796 if (cRects > 0)
797 ExFreePool(rb);
798
799 return Ret;
800 }
801
802 BOOL STDCALL
803 NtGdiPatBlt(
804 HDC hDC,
805 INT XLeft,
806 INT YLeft,
807 INT Width,
808 INT Height,
809 DWORD ROP)
810 {
811 PGDIBRUSHOBJ BrushObj;
812 DC *dc = DC_LockDc(hDC);
813 BOOL ret;
814
815 if (dc == NULL)
816 {
817 SetLastWin32Error(ERROR_INVALID_HANDLE);
818 return FALSE;
819 }
820 if (dc->IsIC)
821 {
822 DC_UnlockDc(dc);
823 /* Yes, Windows really returns TRUE in this case */
824 return TRUE;
825 }
826
827 BrushObj = BRUSHOBJ_LockBrush(dc->w.hBrush);
828 if (BrushObj == NULL)
829 {
830 SetLastWin32Error(ERROR_INVALID_HANDLE);
831 DC_UnlockDc(dc);
832 return FALSE;
833 }
834
835 ret = IntPatBlt(
836 dc,
837 XLeft,
838 YLeft,
839 Width,
840 Height,
841 ROP,
842 BrushObj);
843
844 BRUSHOBJ_UnlockBrush(BrushObj);
845 DC_UnlockDc(dc);
846
847 return ret;
848 }
849
850 /* EOF */