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