xref: /reactos/win32ss/gdi/ntgdi/brush.cpp (revision b5fae844)
1c2c66affSColin Finck /*
2c2c66affSColin Finck  * COPYRIGHT:         See COPYING in the top level directory
3c2c66affSColin Finck  * PROJECT:           ReactOS win32 subsystem
4c2c66affSColin Finck  * PURPOSE:           BRUSH class implementation
5c2c66affSColin Finck  * PROGRAMER:         Timo Kreuzer (timo.kreuzer@reactos.org)
6c2c66affSColin Finck  *
7c2c66affSColin Finck  * REFERENCES:        http://support.microsoft.com/kb/kbview/108497
8c2c66affSColin Finck  */
9c2c66affSColin Finck 
10c2c66affSColin Finck #include "brush.hpp"
11c2c66affSColin Finck 
12c2c66affSColin Finck DBG_DEFAULT_CHANNEL(GdiBrush);
13c2c66affSColin Finck 
BRUSH(_In_ FLONG flAttrs,_In_ COLORREF crColor,_In_ ULONG iHatch,_In_opt_ HBITMAP hbmPattern,_In_opt_ PVOID pvClient,_In_ GDILOOBJTYPE loobjtype=GDILoObjType_LO_BRUSH_TYPE)14c2c66affSColin Finck BRUSH::BRUSH(
15c2c66affSColin Finck     _In_ FLONG flAttrs,
16c2c66affSColin Finck     _In_ COLORREF crColor,
17c2c66affSColin Finck     _In_ ULONG iHatch,
18c2c66affSColin Finck     _In_opt_ HBITMAP hbmPattern,
19c2c66affSColin Finck     _In_opt_ PVOID pvClient,
20c2c66affSColin Finck     _In_ GDILOOBJTYPE loobjtype = GDILoObjType_LO_BRUSH_TYPE)
21c2c66affSColin Finck     : BASEOBJECT(loobjtype)
22c2c66affSColin Finck {
23c2c66affSColin Finck     static ULONG ulGlobalBrushUnique = 0;
24c2c66affSColin Finck 
25c2c66affSColin Finck     /* Get a unique value */
26c2c66affSColin Finck     this->ulBrushUnique = InterlockedIncrementUL(&ulGlobalBrushUnique);
27c2c66affSColin Finck 
28c2c66affSColin Finck     /* Start with kmode brush attribute */
29c2c66affSColin Finck     this->pBrushAttr = &this->BrushAttr;
30c2c66affSColin Finck 
31c2c66affSColin Finck     /* Set parameters */
32c2c66affSColin Finck     this->flAttrs = flAttrs;
33c2c66affSColin Finck     this->iHatch = iHatch;
34c2c66affSColin Finck     this->hbmPattern = hbmPattern;
35c2c66affSColin Finck     this->hbmClient = (HBITMAP)pvClient;
36c2c66affSColin Finck     this->pBrushAttr->lbColor = crColor;
37c2c66affSColin Finck 
38c2c66affSColin Finck     /* Initialize the other fields */
39c2c66affSColin Finck     this->ptOrigin.x = 0;
40c2c66affSColin Finck     this->ptOrigin.y = 0;
41c2c66affSColin Finck     this->bCacheGrabbed = FALSE;
42c2c66affSColin Finck     this->crBack = 0;
43c2c66affSColin Finck     this->crFore = 0;
44c2c66affSColin Finck     this->ulPalTime = 0;
45c2c66affSColin Finck     this->ulSurfTime = 0;
46c2c66affSColin Finck     this->pvRBrush = NULL;
47c2c66affSColin Finck     this->hdev = NULL;
48c2c66affSColin Finck 
49c2c66affSColin Finck     /* FIXME: should be done only in PEN constructor,
50c2c66affSColin Finck        but our destructor needs it! */
51c2c66affSColin Finck     this->dwStyleCount = 0;
52c2c66affSColin Finck     this->pStyle = NULL;
53c2c66affSColin Finck }
54c2c66affSColin Finck 
~BRUSH(VOID)55c2c66affSColin Finck BRUSH::~BRUSH(
56c2c66affSColin Finck     VOID)
57c2c66affSColin Finck {
58c2c66affSColin Finck     /* Check if we have a user mode brush attribute */
59c2c66affSColin Finck     if (this->pBrushAttr != &this->BrushAttr)
60c2c66affSColin Finck     {
61c2c66affSColin Finck         /* Free memory to the process GDI pool */
62c2c66affSColin Finck         GdiPoolFree(GetBrushAttrPool(), this->pBrushAttr);
63c2c66affSColin Finck     }
64c2c66affSColin Finck 
65c2c66affSColin Finck     /* Delete the pattern bitmap (may have already been deleted during gdi cleanup) */
66c2c66affSColin Finck     if (this->hbmPattern != NULL && GreIsHandleValid(this->hbmPattern))
67c2c66affSColin Finck     {
68c2c66affSColin Finck         GreSetBitmapOwner(this->hbmPattern, BASEOBJECT::OWNER::POWNED);
69c2c66affSColin Finck         GreDeleteObject(this->hbmPattern);
70c2c66affSColin Finck     }
71c2c66affSColin Finck 
72c2c66affSColin Finck     /* Delete styles */
73c2c66affSColin Finck     if ((this->pStyle != NULL) && !(this->flAttrs & BR_IS_DEFAULTSTYLE))
74c2c66affSColin Finck     {
75c2c66affSColin Finck         ExFreePoolWithTag(this->pStyle, GDITAG_PENSTYLE);
76c2c66affSColin Finck     }
77c2c66affSColin Finck }
78c2c66affSColin Finck 
79c2c66affSColin Finck VOID
vReleaseAttribute(VOID)80*b5fae844SJames Tabor BRUSH::vReleaseAttribute(VOID)
81*b5fae844SJames Tabor {
82*b5fae844SJames Tabor     if (this->pBrushAttr != &this->BrushAttr)
83*b5fae844SJames Tabor     {
84*b5fae844SJames Tabor         this->BrushAttr = *this->pBrushAttr;
85*b5fae844SJames Tabor         GdiPoolFree(GetBrushAttrPool(), this->pBrushAttr);
86*b5fae844SJames Tabor         this->pBrushAttr = &this->BrushAttr;
87*b5fae844SJames Tabor     }
88*b5fae844SJames Tabor }
89*b5fae844SJames Tabor 
90*b5fae844SJames Tabor VOID
vDeleteObject(_In_ PVOID pvObject)91c2c66affSColin Finck BRUSH::vDeleteObject(
92c2c66affSColin Finck     _In_ PVOID pvObject)
93c2c66affSColin Finck {
94c2c66affSColin Finck     PBRUSH pbr = static_cast<PBRUSH>(pvObject);
95c2c66affSColin Finck     NT_ASSERT((GDI_HANDLE_GET_TYPE(pbr->hHmgr()) == GDILoObjType_LO_BRUSH_TYPE) ||
96c2c66affSColin Finck               (GDI_HANDLE_GET_TYPE(pbr->hHmgr()) == GDILoObjType_LO_PEN_TYPE) ||
97c2c66affSColin Finck               (GDI_HANDLE_GET_TYPE(pbr->hHmgr()) == GDILoObjType_LO_EXTPEN_TYPE));
98c2c66affSColin Finck     delete pbr;
99c2c66affSColin Finck }
100c2c66affSColin Finck 
101c2c66affSColin Finck BOOL
bAllocateBrushAttr(VOID)102c2c66affSColin Finck BRUSH::bAllocateBrushAttr(
103c2c66affSColin Finck     VOID)
104c2c66affSColin Finck {
105c2c66affSColin Finck     PBRUSH_ATTR pBrushAttr;
106c2c66affSColin Finck     NT_ASSERT(this->pBrushAttr == &this->BrushAttr);
107c2c66affSColin Finck 
108c2c66affSColin Finck     /* Allocate a brush attribute from the pool */
109c2c66affSColin Finck     pBrushAttr = static_cast<PBRUSH_ATTR>(GdiPoolAllocate(GetBrushAttrPool()));
110c2c66affSColin Finck     if (pBrushAttr == NULL)
111c2c66affSColin Finck     {
112c2c66affSColin Finck         ERR("Could not allocate brush attr\n");
113c2c66affSColin Finck         return FALSE;
114c2c66affSColin Finck     }
115c2c66affSColin Finck 
116c2c66affSColin Finck     /* Copy the content from the kernel mode brush attribute */
117c2c66affSColin Finck     this->pBrushAttr = pBrushAttr;
118c2c66affSColin Finck     *this->pBrushAttr = this->BrushAttr;
119c2c66affSColin Finck 
120c2c66affSColin Finck     /* Set the object attribute in the handle table */
121c2c66affSColin Finck     vSetObjectAttr(pBrushAttr);
122c2c66affSColin Finck 
123c2c66affSColin Finck     return TRUE;
124c2c66affSColin Finck }
125c2c66affSColin Finck 
126c2c66affSColin Finck VOID
vSetSolidColor(_In_ COLORREF crColor)127c2c66affSColin Finck BRUSH::vSetSolidColor(
128c2c66affSColin Finck     _In_ COLORREF crColor)
129c2c66affSColin Finck {
130c2c66affSColin Finck     NT_ASSERT(this->flAttrs & BR_IS_SOLID);
131c2c66affSColin Finck 
132c2c66affSColin Finck     /* Set new color and reset the pal times */
133c2c66affSColin Finck     this->pBrushAttr->lbColor = crColor & 0xFFFFFF;
134c2c66affSColin Finck     this->ulPalTime = -1;
135c2c66affSColin Finck     this->ulSurfTime = -1;
136c2c66affSColin Finck }
137c2c66affSColin Finck 
138c2c66affSColin Finck HBITMAP
hbmGetBitmapHandle(_Out_ PUINT puUsage) const139c2c66affSColin Finck BRUSH::hbmGetBitmapHandle(
140c2c66affSColin Finck     _Out_ PUINT puUsage) const
141c2c66affSColin Finck {
142c2c66affSColin Finck     /* Return the color usage based on flags */
143c2c66affSColin Finck     *puUsage = (this->flAttrs & BR_IS_DIBPALCOLORS) ? DIB_PAL_COLORS :
144c2c66affSColin Finck                (this->flAttrs & BR_IS_DIBPALINDICES) ? DIB_PAL_INDICES :
145c2c66affSColin Finck                DIB_RGB_COLORS;
146c2c66affSColin Finck 
147c2c66affSColin Finck     return this->hbmPattern;
148c2c66affSColin Finck }
149c2c66affSColin Finck 
150c2c66affSColin Finck UINT
cjGetObject(_In_ UINT cjSize,_Out_bytecap_ (cjSize)PLOGBRUSH plb) const151c2c66affSColin Finck BRUSH::cjGetObject(
152c2c66affSColin Finck     _In_ UINT cjSize,
153c2c66affSColin Finck     _Out_bytecap_(cjSize) PLOGBRUSH plb) const
154c2c66affSColin Finck {
155c2c66affSColin Finck     /* Check if only size is requested */
156c2c66affSColin Finck     if (plb == NULL)
157c2c66affSColin Finck         return sizeof(LOGBRUSH);
158c2c66affSColin Finck 
159c2c66affSColin Finck     /* Check if size is ok */
160c2c66affSColin Finck     if (cjSize == 0)
161c2c66affSColin Finck         return 0;
162c2c66affSColin Finck 
163c2c66affSColin Finck     /* Set color */
164c2c66affSColin Finck     plb->lbColor = this->BrushAttr.lbColor;
165c2c66affSColin Finck 
166c2c66affSColin Finck     /* Set style and hatch based on the attribute flags */
167c2c66affSColin Finck     if (this->flAttrs & BR_IS_SOLID)
168c2c66affSColin Finck     {
169c2c66affSColin Finck         plb->lbStyle = BS_SOLID;
170c2c66affSColin Finck         plb->lbHatch = 0;
171c2c66affSColin Finck     }
172c2c66affSColin Finck     else if (this->flAttrs & BR_IS_HATCH)
173c2c66affSColin Finck     {
174c2c66affSColin Finck         plb->lbStyle = BS_HATCHED;
175c2c66affSColin Finck         plb->lbHatch = this->iHatch;
176c2c66affSColin Finck     }
177c2c66affSColin Finck     else if (this->flAttrs & BR_IS_DIB)
178c2c66affSColin Finck     {
179c2c66affSColin Finck         plb->lbStyle = BS_DIBPATTERN;
180c2c66affSColin Finck         plb->lbHatch = (ULONG_PTR)this->hbmClient;
181c2c66affSColin Finck     }
182c2c66affSColin Finck     else if (this->flAttrs & BR_IS_BITMAP)
183c2c66affSColin Finck     {
184c2c66affSColin Finck         plb->lbStyle = BS_PATTERN;
185c2c66affSColin Finck         plb->lbHatch = (ULONG_PTR)this->hbmClient;
186c2c66affSColin Finck     }
187c2c66affSColin Finck     else if (this->flAttrs & BR_IS_NULL)
188c2c66affSColin Finck     {
189c2c66affSColin Finck         plb->lbStyle = BS_NULL;
190c2c66affSColin Finck         plb->lbHatch = 0;
191c2c66affSColin Finck     }
192c2c66affSColin Finck     else
193c2c66affSColin Finck     {
194c2c66affSColin Finck         NT_ASSERT(FALSE);
195c2c66affSColin Finck     }
196c2c66affSColin Finck 
197c2c66affSColin Finck     return sizeof(LOGBRUSH);
198c2c66affSColin Finck }
199c2c66affSColin Finck 
200c2c66affSColin Finck static
201c2c66affSColin Finck HBRUSH
CreateBrushInternal(_In_ ULONG flAttrs,_In_ COLORREF crColor,_In_ ULONG iHatch,_In_opt_ HBITMAP hbmPattern,_In_opt_ PVOID pvClient)202c2c66affSColin Finck CreateBrushInternal(
203c2c66affSColin Finck     _In_ ULONG flAttrs,
204c2c66affSColin Finck     _In_ COLORREF crColor,
205c2c66affSColin Finck     _In_ ULONG iHatch,
206c2c66affSColin Finck     _In_opt_ HBITMAP hbmPattern,
207c2c66affSColin Finck     _In_opt_ PVOID pvClient)
208c2c66affSColin Finck {
209c2c66affSColin Finck     BASEOBJECT::OWNER owner;
210c2c66affSColin Finck     PBRUSH pbr;
211c2c66affSColin Finck     HBRUSH hbr;
212c2c66affSColin Finck 
213c2c66affSColin Finck     NT_ASSERT(((flAttrs & BR_IS_BITMAP) == 0) || (hbmPattern != NULL));
214c2c66affSColin Finck 
215c2c66affSColin Finck     /* Create the brush (brush takes ownership of the bitmap) */
216c2c66affSColin Finck     pbr = new BRUSH(flAttrs, crColor, iHatch, hbmPattern, pvClient);
217c2c66affSColin Finck     if (pbr == NULL)
218c2c66affSColin Finck     {
219c2c66affSColin Finck         ERR("Failed to allocate a brush\n");
220c2c66affSColin Finck         GreSetBitmapOwner(hbmPattern, BASEOBJECT::OWNER::POWNED);
221c2c66affSColin Finck         GreDeleteObject(hbmPattern);
222c2c66affSColin Finck         return NULL;
223c2c66affSColin Finck     }
224c2c66affSColin Finck 
225c2c66affSColin Finck     /* Check if this is a global brush */
226c2c66affSColin Finck     if (!(flAttrs & BR_IS_GLOBAL))
227c2c66affSColin Finck     {
228c2c66affSColin Finck         /* Not a global brush, so allocate a user mode brush attribute */
229c2c66affSColin Finck         if (!pbr->bAllocateBrushAttr())
230c2c66affSColin Finck         {
231c2c66affSColin Finck             ERR("Failed to allocate brush attribute\n");
232c2c66affSColin Finck             delete pbr;
233c2c66affSColin Finck             return NULL;
234c2c66affSColin Finck         }
235c2c66affSColin Finck     }
236c2c66affSColin Finck 
237c2c66affSColin Finck     /* Set the owner, either public or process owned */
238c2c66affSColin Finck     owner = (flAttrs & BR_IS_GLOBAL) ? BASEOBJECT::OWNER::PUBLIC :
239c2c66affSColin Finck                                        BASEOBJECT::OWNER::POWNED;
240c2c66affSColin Finck 
241c2c66affSColin Finck     /* Insert the object into the GDI handle table */
242c2c66affSColin Finck     hbr =  static_cast<HBRUSH>(pbr->hInsertObject(owner));
243c2c66affSColin Finck     if (hbr == NULL)
244c2c66affSColin Finck     {
245c2c66affSColin Finck         ERR("Failed to insert brush\n");
246c2c66affSColin Finck         delete pbr;
247c2c66affSColin Finck         return NULL;
248c2c66affSColin Finck     }
249c2c66affSColin Finck 
250c2c66affSColin Finck     /* Unlock the brush */
251c2c66affSColin Finck     pbr->vUnlock();
252c2c66affSColin Finck 
253c2c66affSColin Finck     return hbr;
254c2c66affSColin Finck }
255c2c66affSColin Finck 
256c2c66affSColin Finck 
257c2c66affSColin Finck /* C interface ***************************************************************/
258c2c66affSColin Finck 
259c2c66affSColin Finck extern "C" {
260c2c66affSColin Finck 
261c2c66affSColin Finck VOID
262c2c66affSColin Finck NTAPI
BRUSH_vDeleteObject(PVOID pvObject)263c2c66affSColin Finck BRUSH_vDeleteObject(
264c2c66affSColin Finck     PVOID pvObject)
265c2c66affSColin Finck {
266c2c66affSColin Finck     BRUSH::vDeleteObject(pvObject);
267c2c66affSColin Finck }
268c2c66affSColin Finck 
269c2c66affSColin Finck INT
270c2c66affSColin Finck FASTCALL
BRUSH_GetObject(PBRUSH pbr,INT cjBuffer,LPLOGBRUSH plbBuffer)271c2c66affSColin Finck BRUSH_GetObject(
272c2c66affSColin Finck     PBRUSH pbr,
273c2c66affSColin Finck     INT cjBuffer,
274c2c66affSColin Finck     LPLOGBRUSH plbBuffer)
275c2c66affSColin Finck {
276c2c66affSColin Finck     return pbr->cjGetObject(cjBuffer, plbBuffer);
277c2c66affSColin Finck }
278c2c66affSColin Finck 
279c2c66affSColin Finck HBRUSH
280c2c66affSColin Finck NTAPI
IntGdiCreateNullBrush(VOID)281c2c66affSColin Finck IntGdiCreateNullBrush(
282c2c66affSColin Finck     VOID)
283c2c66affSColin Finck {
284c2c66affSColin Finck     /* Call the internal function */
285c2c66affSColin Finck     return CreateBrushInternal(BR_IS_NULL | BR_IS_GLOBAL, 0, 0, NULL, NULL);
286c2c66affSColin Finck }
287c2c66affSColin Finck 
288c2c66affSColin Finck HBRUSH
289c2c66affSColin Finck APIENTRY
IntGdiCreateSolidBrush(COLORREF crColor)290c2c66affSColin Finck IntGdiCreateSolidBrush(
291c2c66affSColin Finck     COLORREF crColor)
292c2c66affSColin Finck {
293c2c66affSColin Finck     /* Call the internal function */
294c2c66affSColin Finck     return CreateBrushInternal(BR_IS_SOLID | BR_IS_GLOBAL,
295c2c66affSColin Finck                                crColor,
296c2c66affSColin Finck                                0,
297c2c66affSColin Finck                                NULL,
298c2c66affSColin Finck                                NULL);
299c2c66affSColin Finck }
300c2c66affSColin Finck 
301c2c66affSColin Finck HBRUSH
302c2c66affSColin Finck NTAPI
IntGdiCreatePatternBrush(HBITMAP hbmPattern)303c2c66affSColin Finck IntGdiCreatePatternBrush(
304c2c66affSColin Finck     HBITMAP hbmPattern)
305c2c66affSColin Finck {
306c2c66affSColin Finck     NT_ASSERT(hbmPattern != NULL);
307c2c66affSColin Finck     GreSetBitmapOwner(hbmPattern, BASEOBJECT::OWNER::PUBLIC);
308c2c66affSColin Finck     return CreateBrushInternal(BR_IS_BITMAP | BR_IS_GLOBAL,
309c2c66affSColin Finck                                0,
310c2c66affSColin Finck                                0,
311c2c66affSColin Finck                                hbmPattern,
312c2c66affSColin Finck                                NULL);
313c2c66affSColin Finck }
314c2c66affSColin Finck 
315c2c66affSColin Finck VOID
316c2c66affSColin Finck NTAPI
IntGdiSetSolidBrushColor(_In_ HBRUSH hbr,_In_ COLORREF crColor)317c2c66affSColin Finck IntGdiSetSolidBrushColor(
318c2c66affSColin Finck     _In_ HBRUSH hbr,
319c2c66affSColin Finck     _In_ COLORREF crColor)
320c2c66affSColin Finck {
321c2c66affSColin Finck     PBRUSH pbr;
322c2c66affSColin Finck 
323c2c66affSColin Finck     /* Lock the brush */
324c2c66affSColin Finck     pbr = BRUSH::LockAny(hbr);
325c2c66affSColin Finck     if (pbr == NULL)
326c2c66affSColin Finck     {
327c2c66affSColin Finck         ERR("Failed to lock brush %p\n", hbr);
328c2c66affSColin Finck         return;
329c2c66affSColin Finck     }
330c2c66affSColin Finck 
331c2c66affSColin Finck     /* Call the member function */
332c2c66affSColin Finck     pbr->vSetSolidColor(crColor);
333c2c66affSColin Finck 
334c2c66affSColin Finck     /* Unlock the brush */
335c2c66affSColin Finck     pbr->vUnlock();
336c2c66affSColin Finck }
337c2c66affSColin Finck 
338c2c66affSColin Finck __kernel_entry
339c2c66affSColin Finck HBRUSH
340c2c66affSColin Finck APIENTRY
NtGdiCreateSolidBrush(_In_ COLORREF crColor,_In_opt_ HBRUSH hbr)341c2c66affSColin Finck NtGdiCreateSolidBrush(
342c2c66affSColin Finck     _In_ COLORREF crColor,
343c2c66affSColin Finck     _In_opt_ HBRUSH hbr)
344c2c66affSColin Finck {
345c2c66affSColin Finck     if (hbr != NULL)
346c2c66affSColin Finck     {
347c2c66affSColin Finck         WARN("hbr is not supported, ignoring\n");
348c2c66affSColin Finck     }
349c2c66affSColin Finck 
350c2c66affSColin Finck     /* Call the internal function */
351c2c66affSColin Finck     return CreateBrushInternal(BR_IS_SOLID, crColor, 0, NULL, NULL);
352c2c66affSColin Finck }
353c2c66affSColin Finck 
354c2c66affSColin Finck __kernel_entry
355c2c66affSColin Finck HBRUSH
356c2c66affSColin Finck APIENTRY
NtGdiCreateHatchBrushInternal(_In_ ULONG iHatch,_In_ COLORREF crColor,_In_ BOOL bPen)357c2c66affSColin Finck NtGdiCreateHatchBrushInternal(
358c2c66affSColin Finck     _In_ ULONG iHatch,
359c2c66affSColin Finck     _In_ COLORREF crColor,
360c2c66affSColin Finck     _In_ BOOL bPen)
361c2c66affSColin Finck {
362c2c66affSColin Finck     FLONG flAttr;
363c2c66affSColin Finck 
364c2c66affSColin Finck     if (bPen)
365c2c66affSColin Finck     {
366c2c66affSColin Finck         WARN("bPen is not supported, ignoring\n");
367c2c66affSColin Finck     }
368c2c66affSColin Finck 
369c2c66affSColin Finck     /* Check what kind if hatch style this is */
370c2c66affSColin Finck     if (iHatch < HS_DDI_MAX)
371c2c66affSColin Finck     {
372c2c66affSColin Finck         flAttr = BR_IS_HATCH;
373c2c66affSColin Finck     }
374c2c66affSColin Finck     else if (iHatch < HS_API_MAX)
375c2c66affSColin Finck     {
376c2c66affSColin Finck         flAttr = BR_IS_SOLID;
377c2c66affSColin Finck     }
378c2c66affSColin Finck     else
379c2c66affSColin Finck     {
380c2c66affSColin Finck         ERR("Invalid iHatch: %lu\n", iHatch);
381c2c66affSColin Finck         return NULL;
382c2c66affSColin Finck     }
383c2c66affSColin Finck 
384c2c66affSColin Finck     /* Call the internal function */
385c2c66affSColin Finck     return CreateBrushInternal(flAttr, crColor, iHatch, NULL, NULL);
386c2c66affSColin Finck }
387c2c66affSColin Finck 
388c2c66affSColin Finck __kernel_entry
389c2c66affSColin Finck HBRUSH
390c2c66affSColin Finck APIENTRY
NtGdiCreatePatternBrushInternal(_In_ HBITMAP hbmClient,_In_ BOOL bPen,_In_ BOOL b8X8)391c2c66affSColin Finck NtGdiCreatePatternBrushInternal(
392c2c66affSColin Finck     _In_ HBITMAP hbmClient,
393c2c66affSColin Finck     _In_ BOOL bPen,
394c2c66affSColin Finck     _In_ BOOL b8X8)
395c2c66affSColin Finck {
396c2c66affSColin Finck     HBITMAP hbmPattern;
397c2c66affSColin Finck 
398c2c66affSColin Finck     if (b8X8)
399c2c66affSColin Finck     {
400c2c66affSColin Finck         WARN("b8X8 is not supported, ignoring\n");
401c2c66affSColin Finck     }
402c2c66affSColin Finck 
403c2c66affSColin Finck     if (bPen)
404c2c66affSColin Finck     {
405c2c66affSColin Finck         WARN("bPen is not supported, ignoring\n");
406c2c66affSColin Finck     }
407c2c66affSColin Finck 
408c2c66affSColin Finck     /* Copy the bitmap */
409c2c66affSColin Finck     hbmPattern = BITMAP_CopyBitmap(hbmClient);
410c2c66affSColin Finck     if (hbmPattern == NULL)
411c2c66affSColin Finck     {
412c2c66affSColin Finck         ERR("Failed to copy the bitmap %p\n", hbmPattern);
413c2c66affSColin Finck         return NULL;
414c2c66affSColin Finck     }
415c2c66affSColin Finck 
416c2c66affSColin Finck     /* Call the internal function (will delete hbmPattern on failure) */
417c2c66affSColin Finck     return CreateBrushInternal(BR_IS_BITMAP, 0, 0, hbmPattern, hbmClient);
418c2c66affSColin Finck }
419c2c66affSColin Finck 
420c2c66affSColin Finck __kernel_entry
421c2c66affSColin Finck HBRUSH
422c2c66affSColin Finck APIENTRY
NtGdiCreateDIBBrush(_In_reads_bytes_ (cj)PVOID pv,_In_ FLONG uUsage,_In_ UINT cj,_In_ BOOL b8X8,_In_ BOOL bPen,_In_ PVOID pvClient)423c2c66affSColin Finck NtGdiCreateDIBBrush(
424c2c66affSColin Finck     _In_reads_bytes_(cj) PVOID pv,
425c2c66affSColin Finck     _In_ FLONG uUsage,
426c2c66affSColin Finck     _In_ UINT cj,
427c2c66affSColin Finck     _In_ BOOL b8X8,
428c2c66affSColin Finck     _In_ BOOL bPen,
429c2c66affSColin Finck     _In_ PVOID pvClient)
430c2c66affSColin Finck {
431c2c66affSColin Finck     PVOID pvPackedDIB;
432c2c66affSColin Finck     FLONG flAttrs;
433c2c66affSColin Finck     HBITMAP hbm;
434c2c66affSColin Finck     HBRUSH hbr = NULL;
435c2c66affSColin Finck 
436c2c66affSColin Finck     if (b8X8)
437c2c66affSColin Finck     {
438c2c66affSColin Finck         WARN("b8X8 is not supported, ignoring\n");
439c2c66affSColin Finck     }
440c2c66affSColin Finck 
441c2c66affSColin Finck     if (bPen)
442c2c66affSColin Finck     {
443c2c66affSColin Finck         WARN("bPen is not supported, ignoring\n");
444c2c66affSColin Finck     }
445c2c66affSColin Finck 
446c2c66affSColin Finck     if (uUsage > DIB_PAL_INDICES)
447c2c66affSColin Finck     {
448c2c66affSColin Finck         ERR("Invalid uUsage value: %lu\n", uUsage);
449c2c66affSColin Finck         EngSetLastError(ERROR_INVALID_PARAMETER);
450c2c66affSColin Finck         return NULL;
451c2c66affSColin Finck     }
452c2c66affSColin Finck 
453c2c66affSColin Finck     /* Allocate a buffer for the packed DIB */
454c2c66affSColin Finck     pvPackedDIB = ExAllocatePoolWithTag(PagedPool, cj, GDITAG_TEMP);
455c2c66affSColin Finck     if (pvPackedDIB == NULL)
456c2c66affSColin Finck     {
457c2c66affSColin Finck         ERR("Failed to allocate temp buffer of %u bytes\n", cj);
458c2c66affSColin Finck         return NULL;
459c2c66affSColin Finck     }
460c2c66affSColin Finck 
461c2c66affSColin Finck     /* Probe and copy the packed DIB */
462c2c66affSColin Finck     _SEH2_TRY
463c2c66affSColin Finck     {
464c2c66affSColin Finck         ProbeForRead(pv, cj, 1);
465c2c66affSColin Finck         RtlCopyMemory(pvPackedDIB, pv, cj);
466c2c66affSColin Finck     }
467c2c66affSColin Finck     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
468c2c66affSColin Finck     {
469c2c66affSColin Finck         ERR("Got exception, pv = %p, cj = %lu\n", pv, cj);
470c2c66affSColin Finck         goto cleanup;
471c2c66affSColin Finck     }
472c2c66affSColin Finck     _SEH2_END;
473c2c66affSColin Finck 
474c2c66affSColin Finck     flAttrs = BR_IS_BITMAP | BR_IS_DIB;
475c2c66affSColin Finck 
476c2c66affSColin Finck     /* Check what kind of color table we have */
477c2c66affSColin Finck     if (uUsage == DIB_PAL_COLORS)
478c2c66affSColin Finck     {
479c2c66affSColin Finck         /* Remember it and use DIB_PAL_BRUSHHACK to create a "special" palette */
480c2c66affSColin Finck         flAttrs |= BR_IS_DIBPALCOLORS;
481c2c66affSColin Finck         uUsage = DIB_PAL_BRUSHHACK;
482c2c66affSColin Finck     }
483c2c66affSColin Finck     else if (uUsage == DIB_PAL_INDICES)
484c2c66affSColin Finck     {
485c2c66affSColin Finck         /* No color table, bitmap contains device palette indices */
486c2c66affSColin Finck         flAttrs |= BR_IS_DIBPALINDICES;
487c2c66affSColin Finck 
488c2c66affSColin Finck         /* FIXME: This makes tests pass, but needs investigation. */
489c2c66affSColin Finck         flAttrs |= BR_IS_NULL;
490c2c66affSColin Finck     }
491c2c66affSColin Finck 
492c2c66affSColin Finck     /* Create a bitmap from the DIB */
493c2c66affSColin Finck     hbm = GreCreateDIBitmapFromPackedDIB(pvPackedDIB, cj, uUsage);
494c2c66affSColin Finck     if (hbm == NULL)
495c2c66affSColin Finck     {
496c2c66affSColin Finck         ERR("Failed to create bitmap from DIB\n");
497c2c66affSColin Finck         goto cleanup;
498c2c66affSColin Finck     }
499c2c66affSColin Finck 
500c2c66affSColin Finck     /* Call the internal function (will delete hbm on failure) */
501c2c66affSColin Finck     hbr = CreateBrushInternal(flAttrs, 0, 0, hbm, pvClient);
502c2c66affSColin Finck 
503c2c66affSColin Finck cleanup:
504c2c66affSColin Finck 
505c2c66affSColin Finck     ExFreePoolWithTag(pvPackedDIB, GDITAG_TEMP);
506c2c66affSColin Finck 
507c2c66affSColin Finck     return hbr;
508c2c66affSColin Finck }
509c2c66affSColin Finck 
510c2c66affSColin Finck __kernel_entry
511c2c66affSColin Finck HBITMAP
512c2c66affSColin Finck APIENTRY
NtGdiGetObjectBitmapHandle(_In_ HBRUSH hbr,_Out_ UINT * piUsage)513c2c66affSColin Finck NtGdiGetObjectBitmapHandle(
514c2c66affSColin Finck     _In_ HBRUSH hbr,
515c2c66affSColin Finck     _Out_ UINT *piUsage)
516c2c66affSColin Finck {
517c2c66affSColin Finck     PBRUSH pbr;
518c2c66affSColin Finck     HBITMAP hbm;
519c2c66affSColin Finck     UINT uUsage;
520c2c66affSColin Finck 
521c2c66affSColin Finck     /* Lock the brush */
522c2c66affSColin Finck     pbr = BRUSH::LockForRead(hbr);
523c2c66affSColin Finck     if (pbr == NULL)
524c2c66affSColin Finck     {
525c2c66affSColin Finck         ERR("Failed to lock brush %p\n", hbr);
526c2c66affSColin Finck         return NULL;
527c2c66affSColin Finck     }
528c2c66affSColin Finck 
529c2c66affSColin Finck     /* Call the member function */
530c2c66affSColin Finck     hbm = pbr->hbmGetBitmapHandle(&uUsage);
531c2c66affSColin Finck 
532c2c66affSColin Finck     /* Unlock the brush */
533c2c66affSColin Finck     pbr->vUnlock();
534c2c66affSColin Finck 
535c2c66affSColin Finck     _SEH2_TRY
536c2c66affSColin Finck     {
537c2c66affSColin Finck         ProbeForWrite(piUsage, sizeof(*piUsage), 1);
538c2c66affSColin Finck         *piUsage = uUsage;
539c2c66affSColin Finck     }
540c2c66affSColin Finck     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
541c2c66affSColin Finck     {
542c2c66affSColin Finck         ERR("Got exception! piUsage = %p\n", piUsage);
543c2c66affSColin Finck         hbm = NULL;
544c2c66affSColin Finck     }
545c2c66affSColin Finck     _SEH2_END;
546c2c66affSColin Finck 
547c2c66affSColin Finck     return hbm;
548c2c66affSColin Finck }
549c2c66affSColin Finck 
550c2c66affSColin Finck __kernel_entry
551c2c66affSColin Finck HBRUSH
552c2c66affSColin Finck APIENTRY
NtGdiSetBrushAttributes(_In_ HBRUSH hbr,_In_ DWORD dwFlags)553c2c66affSColin Finck NtGdiSetBrushAttributes(
554c2c66affSColin Finck     _In_ HBRUSH hbr,
555c2c66affSColin Finck     _In_ DWORD dwFlags)
556c2c66affSColin Finck {
557*b5fae844SJames Tabor     PBRUSH pbr;
558970344bdSJames Tabor     if ( dwFlags & SC_BB_STOCKOBJ )
559970344bdSJames Tabor     {
560970344bdSJames Tabor         if (GDIOBJ_ConvertToStockObj((HGDIOBJ*)&hbr))
561970344bdSJames Tabor         {
562*b5fae844SJames Tabor             pbr = BRUSH::LockAny(hbr);
563*b5fae844SJames Tabor             if (pbr == NULL)
564*b5fae844SJames Tabor             {
565*b5fae844SJames Tabor                 ERR("Failed to lock brush %p\n", hbr);
566*b5fae844SJames Tabor                 return NULL;
567*b5fae844SJames Tabor             }
568*b5fae844SJames Tabor             pbr->vReleaseAttribute();
569*b5fae844SJames Tabor             pbr->vUnlock();
570970344bdSJames Tabor             return hbr;
571970344bdSJames Tabor         }
572970344bdSJames Tabor     }
573c2c66affSColin Finck     return NULL;
574c2c66affSColin Finck }
575c2c66affSColin Finck 
576c2c66affSColin Finck __kernel_entry
577c2c66affSColin Finck HBRUSH
578c2c66affSColin Finck APIENTRY
NtGdiClearBrushAttributes(_In_ HBRUSH hbr,_In_ DWORD dwFlags)579c2c66affSColin Finck NtGdiClearBrushAttributes(
580c2c66affSColin Finck     _In_ HBRUSH hbr,
581c2c66affSColin Finck     _In_ DWORD dwFlags)
582c2c66affSColin Finck {
583*b5fae844SJames Tabor     PBRUSH pbr;
584970344bdSJames Tabor     if ( dwFlags & SC_BB_STOCKOBJ )
585970344bdSJames Tabor     {
586970344bdSJames Tabor         if (GDIOBJ_ConvertFromStockObj((HGDIOBJ*)&hbr))
587970344bdSJames Tabor         {
588*b5fae844SJames Tabor             pbr = BRUSH::LockAny(hbr);
589*b5fae844SJames Tabor             if (pbr == NULL)
590*b5fae844SJames Tabor             {
591*b5fae844SJames Tabor                 ERR("Failed to lock brush %p\n", hbr);
592*b5fae844SJames Tabor                 return NULL;
593*b5fae844SJames Tabor             }
594*b5fae844SJames Tabor             if (!pbr->bAllocateBrushAttr())
595*b5fae844SJames Tabor             {
596*b5fae844SJames Tabor                 ERR("Failed to allocate brush attribute\n");
597*b5fae844SJames Tabor             }
598*b5fae844SJames Tabor             pbr->vUnlock();
599970344bdSJames Tabor             return hbr;
600970344bdSJames Tabor         }
601970344bdSJames Tabor     }
602c2c66affSColin Finck     return NULL;
603c2c66affSColin Finck }
604c2c66affSColin Finck 
605c2c66affSColin Finck } /* extern "C" */
606