Rewrite brush code in C++

svn path=/trunk/; revision=66893
This commit is contained in:
Timo Kreuzer 2015-03-25 22:38:20 +00:00
parent ec0f3d9ba9
commit 976a3274ad
8 changed files with 825 additions and 566 deletions

View file

@ -1,6 +1,11 @@
set(USE_DIBLIB FALSE)
if(NOT MSVC)
# HACK: this should be enabled globally!
add_compile_flags_language("-std=c++11" "CXX")
endif()
# Give WIN32 subsystem its own project.
PROJECT(WIN32SS)
@ -146,7 +151,7 @@ list(APPEND SOURCE
gdi/ntgdi/bezier.c
gdi/ntgdi/bitblt.c
gdi/ntgdi/bitmaps.c
gdi/ntgdi/brush.c
gdi/ntgdi/brush.cpp
gdi/ntgdi/cliprgn.c
gdi/ntgdi/coord.c
gdi/ntgdi/dcattr.c
@ -227,7 +232,7 @@ if(USE_DIBLIB)
endif()
add_importlibs(win32k ntoskrnl hal ftfd)
add_pch(win32k pch.h SOURCE)
#add_pch(win32k pch.h SOURCE)
add_cd_file(TARGET win32k DESTINATION reactos/system32 FOR all)
set_source_files_properties(sys-stubs.S PROPERTIES OBJECT_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/w32ksvc.h)

View file

@ -0,0 +1,109 @@
#pragma once
#define GDIOBJ_POOL_TAG(type) ('00hG' + (((type) & 0x1f) << 24))
#define BASEOBJECT CBASEOBJECT
class BASEOBJECT : private _BASEOBJECT
{
public:
enum OWNER
{
POWNED = GDI_OBJ_HMGR_POWNED,
PUBLIC = GDI_OBJ_HMGR_PUBLIC,
NONE = GDI_OBJ_HMGR_NONE
};
protected:
BASEOBJECT(
_In_ GDILOOBJTYPE loobjtype)
{
/* Initialize the object */
_BASEOBJECT::hHmgr = (HGDIOBJ)(ULONG_PTR)loobjtype;
this->cExclusiveLock = 0;
this->ulShareCount = 1;
this->BaseFlags = 0;//fl & 0xffff;
DBG_INITLOG(&this->slhLog);
DBG_LOGEVENT(&this->slhLog, EVENT_ALLOCATE, 0);
#if DBG_ENABLE_GDIOBJ_BACKTRACES
DbgCaptureStackBackTace(this->apvBackTrace, 1, GDI_OBJECT_STACK_LEVELS);
#endif /* GDI_DEBUG */
}
static
BASEOBJECT*
LockExclusive(
HGDIOBJ hobj,
GDIOBJTYPE objtype);
static
BASEOBJECT*
LockExclusive(
HGDIOBJ hobj,
GDILOOBJTYPE loobjtype);
static
BASEOBJECT*
LockShared(
HGDIOBJ hobj,
GDILOOBJTYPE loobjtype,
OWNER owner)
{
return 0;
}
VOID
vSetObjectAttr(
_In_opt_ PVOID pvUserAttr)
{
GDIOBJ_vSetObjectAttr((POBJ)this, pvUserAttr);
}
public:
static
inline
PVOID
pvAllocate(
_In_ GDIOBJTYPE objtype,
_In_ SIZE_T cjSize)
{
return ExAllocatePoolWithTag(PagedPool, cjSize, GDIOBJ_POOL_TAG(objtype));
}
VOID
vUnlock(
VOID)
{
if (this->cExclusiveLock > 0)
{
GDIOBJ_vUnlockObject(this);
}
else
{
GDIOBJ_vDereferenceObject(this);
}
}
inline
HGDIOBJ
hHmgr(
VOID)
{
return _BASEOBJECT::hHmgr;
}
HGDIOBJ
hInsertObject(
OWNER owner)
{
return GDIOBJ_hInsertObject(this, owner);
}
};

View file

@ -1,563 +0,0 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS win32 subsystem
* PURPOSE: Functions for brushes
* FILE: subsystem/win32/win32k/objects/brush.c
* PROGRAMER:
*/
#include <win32k.h>
#define NDEBUG
#include <debug.h>
static
VOID
BRUSH_vInit(
PBRUSH pbr)
{
/* Start with kmode brush attribute */
pbr->pBrushAttr = &pbr->BrushAttr;
}
static
PBRUSH
BRUSH_AllocBrushWithHandle(
VOID)
{
PBRUSH pbr;
pbr = (PBRUSH)GDIOBJ_AllocObjWithHandle(GDILoObjType_LO_BRUSH_TYPE, sizeof(BRUSH));
if (pbr == NULL)
{
return NULL;
}
BRUSH_vInit(pbr);
return pbr;
}
static
BOOL
BRUSH_bAllocBrushAttr(PBRUSH pbr)
{
PPROCESSINFO ppi;
BRUSH_ATTR *pBrushAttr;
NT_ASSERT(pbr->pBrushAttr == &pbr->BrushAttr);
ppi = PsGetCurrentProcessWin32Process();
NT_ASSERT(ppi);
__analysis_assume(ppi);
pBrushAttr = GdiPoolAllocate(ppi->pPoolBrushAttr);
if (!pBrushAttr)
{
DPRINT1("Could not allocate brush attr\n");
return FALSE;
}
/* Copy the content from the kernel mode dc attr */
pbr->pBrushAttr = pBrushAttr;
*pbr->pBrushAttr = pbr->BrushAttr;
/* Set the object attribute in the handle table */
GDIOBJ_vSetObjectAttr(&pbr->BaseObject, pBrushAttr);
DPRINT("BRUSH_bAllocBrushAttr: pbr=%p, pbr->pdcattr=%p\n", pbr, pbr->pBrushAttr);
return TRUE;
}
static
VOID
BRUSH_vFreeBrushAttr(PBRUSH pbr)
{
PPROCESSINFO ppi;
if (pbr->pBrushAttr == &pbr->BrushAttr) return;
/* Reset the object attribute in the handle table */
GDIOBJ_vSetObjectAttr(&pbr->BaseObject, NULL);
/* Free memory from the process gdi pool */
ppi = PsGetCurrentProcessWin32Process();
ASSERT(ppi);
GdiPoolFree(ppi->pPoolBrushAttr, pbr->pBrushAttr);
/* Reset to kmode brush attribute */
pbr->pBrushAttr = &pbr->BrushAttr;
}
BOOL
FASTCALL
IntGdiSetBrushOwner(PBRUSH pbr, ULONG ulOwner)
{
// FIXME:
if (pbr->flAttrs & BR_IS_GLOBAL) return TRUE;
if ((ulOwner == GDI_OBJ_HMGR_PUBLIC) || ulOwner == GDI_OBJ_HMGR_NONE)
{
/* Free user mode attribute, if any */
BRUSH_vFreeBrushAttr(pbr);
// Deny user access to User Data.
GDIOBJ_vSetObjectAttr(&pbr->BaseObject, NULL);
}
if (ulOwner == GDI_OBJ_HMGR_POWNED)
{
/* Allocate a user mode attribute */
BRUSH_bAllocBrushAttr(pbr);
// Allow user access to User Data.
GDIOBJ_vSetObjectAttr(&pbr->BaseObject, pbr->pBrushAttr);
}
GDIOBJ_vSetObjectOwner(&pbr->BaseObject, ulOwner);
return TRUE;
}
BOOL
FASTCALL
GreSetBrushOwner(HBRUSH hBrush, ULONG ulOwner)
{
BOOL Ret;
PBRUSH pbrush;
pbrush = BRUSH_ShareLockBrush(hBrush);
Ret = IntGdiSetBrushOwner(pbrush, ulOwner);
BRUSH_ShareUnlockBrush(pbrush);
return Ret;
}
VOID
NTAPI
BRUSH_vCleanup(PVOID ObjectBody)
{
PBRUSH pbrush = (PBRUSH)ObjectBody;
if (pbrush->hbmPattern)
{
GreSetObjectOwner(pbrush->hbmPattern, GDI_OBJ_HMGR_POWNED);
GreDeleteObject(pbrush->hbmPattern);
}
/* Check if there is a usermode attribute */
if (pbrush->pBrushAttr != &pbrush->BrushAttr)
{
BRUSH_vFreeBrushAttr(pbrush);
}
/* Free the kmode styles array of EXTPENS */
if (pbrush->pStyle)
{
ExFreePool(pbrush->pStyle);
}
}
VOID
NTAPI
BRUSH_vDeleteObject(
PVOID pvObject)
{
BRUSH_vCleanup(pvObject);
ExFreePoolWithTag(pvObject, GDITAG_HMGR_BRUSH_TYPE);
}
INT
FASTCALL
BRUSH_GetObject(PBRUSH pbrush, INT cjSize, LPLOGBRUSH plogbrush)
{
/* Check if only size is requested */
if (plogbrush == NULL) return sizeof(LOGBRUSH);
/* Check if size is ok */
if (cjSize == 0) return 0;
/* Set colour */
plogbrush->lbColor = pbrush->BrushAttr.lbColor;
/* Default to 0 */
plogbrush->lbHatch = 0;
/* Get the type of style */
if (pbrush->flAttrs & BR_IS_SOLID)
{
plogbrush->lbStyle = BS_SOLID;
}
else if (pbrush->flAttrs & BR_IS_NULL)
{
plogbrush->lbStyle = BS_NULL; // BS_HOLLOW
}
else if (pbrush->flAttrs & BR_IS_HATCH)
{
plogbrush->lbStyle = BS_HATCHED;
plogbrush->lbHatch = pbrush->iHatch;
}
else if (pbrush->flAttrs & BR_IS_DIB)
{
plogbrush->lbStyle = BS_DIBPATTERN;
plogbrush->lbHatch = (ULONG_PTR)pbrush->hbmClient;
}
else if (pbrush->flAttrs & BR_IS_BITMAP)
{
plogbrush->lbStyle = BS_PATTERN;
}
else
{
plogbrush->lbStyle = 0; // ???
}
/* FIXME
else if (pbrush->flAttrs & )
{
plogbrush->lbStyle = BS_INDEXED;
}
else if (pbrush->flAttrs & )
{
plogbrush->lbStyle = BS_DIBPATTERNPT;
}
*/
/* FIXME */
return sizeof(LOGBRUSH);
}
HBRUSH
APIENTRY
IntGdiCreateDIBBrush(
const BITMAPINFO *BitmapInfo,
UINT uUsage,
UINT BitmapInfoSize,
const VOID* pvClient)
{
HBRUSH hBrush;
PBRUSH pbrush;
HBITMAP hPattern;
ULONG_PTR DataPtr;
PVOID pvDIBits;
if (BitmapInfo->bmiHeader.biSize < sizeof(BITMAPINFOHEADER))
{
EngSetLastError(ERROR_INVALID_PARAMETER);
return NULL;
}
DataPtr = (ULONG_PTR)BitmapInfo + DIB_BitmapInfoSize(BitmapInfo, uUsage);
hPattern = DIB_CreateDIBSection(NULL, BitmapInfo, uUsage, &pvDIBits, NULL, 0, 0);
if (hPattern == NULL)
{
EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
return NULL;
}
RtlCopyMemory(pvDIBits,
(PVOID)DataPtr,
DIB_GetDIBImageBytes(BitmapInfo->bmiHeader.biWidth,
BitmapInfo->bmiHeader.biHeight,
BitmapInfo->bmiHeader.biBitCount * BitmapInfo->bmiHeader.biPlanes));
pbrush = BRUSH_AllocBrushWithHandle();
if (pbrush == NULL)
{
GreDeleteObject(hPattern);
EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
return NULL;
}
hBrush = pbrush->BaseObject.hHmgr;
pbrush->flAttrs |= BR_IS_BITMAP | BR_IS_DIB;
if (uUsage == DIB_PAL_COLORS)
pbrush->flAttrs |= BR_IS_DIBPALCOLORS;
pbrush->hbmPattern = hPattern;
pbrush->hbmClient = (HBITMAP)pvClient;
/* FIXME: Fill in the rest of fields!!! */
GreSetObjectOwner(hPattern, GDI_OBJ_HMGR_PUBLIC);
GDIOBJ_vUnlockObject(&pbrush->BaseObject);
return hBrush;
}
HBRUSH
APIENTRY
IntGdiCreateHatchBrush(
INT Style,
COLORREF Color)
{
HBRUSH hBrush;
PBRUSH pbrush;
if (Style < 0 || Style >= NB_HATCH_STYLES)
{
return 0;
}
pbrush = BRUSH_AllocBrushWithHandle();
if (pbrush == NULL)
{
EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
return NULL;
}
hBrush = pbrush->BaseObject.hHmgr;
pbrush->flAttrs |= BR_IS_HATCH;
pbrush->BrushAttr.lbColor = Color & 0xFFFFFF;
pbrush->iHatch = Style;
GDIOBJ_vUnlockObject(&pbrush->BaseObject);
return hBrush;
}
HBRUSH
APIENTRY
IntGdiCreatePatternBrush(
HBITMAP hBitmap)
{
HBRUSH hBrush;
PBRUSH pbrush;
HBITMAP hPattern;
hPattern = BITMAP_CopyBitmap(hBitmap);
if (hPattern == NULL)
{
EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
return NULL;
}
pbrush = BRUSH_AllocBrushWithHandle();
if (pbrush == NULL)
{
GreDeleteObject(hPattern);
EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
return NULL;
}
hBrush = pbrush->BaseObject.hHmgr;
pbrush->flAttrs |= BR_IS_BITMAP;
pbrush->hbmPattern = hPattern;
/* FIXME: Fill in the rest of fields!!! */
GreSetObjectOwner(hPattern, GDI_OBJ_HMGR_PUBLIC);
GDIOBJ_vUnlockObject(&pbrush->BaseObject);
return hBrush;
}
HBRUSH
APIENTRY
IntGdiCreateSolidBrush(
COLORREF Color)
{
HBRUSH hBrush;
PBRUSH pbrush;
pbrush = BRUSH_AllocBrushWithHandle();
if (pbrush == NULL)
{
EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
return NULL;
}
hBrush = pbrush->BaseObject.hHmgr;
pbrush->flAttrs |= BR_IS_SOLID;
pbrush->BrushAttr.lbColor = Color & 0x00FFFFFF;
/* FIXME: Fill in the rest of fields!!! */
GDIOBJ_vUnlockObject(&pbrush->BaseObject);
return hBrush;
}
HBRUSH
APIENTRY
IntGdiCreateNullBrush(VOID)
{
HBRUSH hBrush;
PBRUSH pbrush;
pbrush = BRUSH_AllocBrushWithHandle();
if (pbrush == NULL)
{
EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
return NULL;
}
hBrush = pbrush->BaseObject.hHmgr;
pbrush->flAttrs |= BR_IS_NULL;
GDIOBJ_vUnlockObject(&pbrush->BaseObject);
return hBrush;
}
VOID
NTAPI
IntGdiSetSolidBrushColor(HBRUSH hBrush, COLORREF Color)
{
PBRUSH pbrush;
pbrush = BRUSH_ShareLockBrush(hBrush);
if (pbrush->flAttrs & BR_IS_SOLID)
{
pbrush->BrushAttr.lbColor = Color & 0xFFFFFF;
}
BRUSH_ShareUnlockBrush(pbrush);
}
/* PUBLIC FUNCTIONS ***********************************************************/
HBRUSH
APIENTRY
NtGdiCreateDIBBrush(
IN PVOID BitmapInfoAndData,
IN FLONG ColorSpec,
IN UINT BitmapInfoSize,
IN BOOL b8X8,
IN BOOL bPen,
IN PVOID PackedDIB)
{
BITMAPINFO *SafeBitmapInfoAndData;
NTSTATUS Status = STATUS_SUCCESS;
HBRUSH hBrush;
SafeBitmapInfoAndData = EngAllocMem(FL_ZERO_MEMORY, BitmapInfoSize, TAG_DIB);
if (SafeBitmapInfoAndData == NULL)
{
EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
return NULL;
}
_SEH2_TRY
{
ProbeForRead(BitmapInfoAndData, BitmapInfoSize, 1);
RtlCopyMemory(SafeBitmapInfoAndData, BitmapInfoAndData, BitmapInfoSize);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
Status = _SEH2_GetExceptionCode();
}
_SEH2_END;
if (!NT_SUCCESS(Status))
{
EngFreeMem(SafeBitmapInfoAndData);
SetLastNtError(Status);
return 0;
}
hBrush = IntGdiCreateDIBBrush(SafeBitmapInfoAndData,
ColorSpec,
BitmapInfoSize,
PackedDIB);
EngFreeMem(SafeBitmapInfoAndData);
return hBrush;
}
HBRUSH
APIENTRY
NtGdiCreateHatchBrushInternal(
ULONG Style,
COLORREF Color,
BOOL bPen)
{
return IntGdiCreateHatchBrush(Style, Color);
}
HBRUSH
APIENTRY
NtGdiCreatePatternBrushInternal(
HBITMAP hBitmap,
BOOL bPen,
BOOL b8x8)
{
return IntGdiCreatePatternBrush(hBitmap);
}
HBRUSH
APIENTRY
NtGdiCreateSolidBrush(COLORREF Color,
IN OPTIONAL HBRUSH hbr)
{
return IntGdiCreateSolidBrush(Color);
}
HBITMAP
APIENTRY
NtGdiGetObjectBitmapHandle(
_In_ HBRUSH hbr,
_Out_ UINT *piUsage)
{
HBITMAP hbmPattern;
PBRUSH pbr;
/* Lock the brush */
pbr = BRUSH_ShareLockBrush(hbr);
if (pbr == NULL)
{
DPRINT1("Could not lock brush\n");
return NULL;
}
/* Get the pattern bitmap handle */
hbmPattern = pbr->hbmPattern;
_SEH2_TRY
{
ProbeForWrite(piUsage, sizeof(*piUsage), sizeof(*piUsage));
/* Set usage according to flags */
if (pbr->flAttrs & BR_IS_DIBPALCOLORS)
*piUsage = DIB_PAL_COLORS;
else
*piUsage = DIB_RGB_COLORS;
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
DPRINT1("Got exception!\n");
hbmPattern = NULL;
}
_SEH2_END;
/* Unlock the brush */
BRUSH_ShareUnlockBrush(pbr);
/* Return the pattern bitmap handle */
return hbmPattern;
}
/*
* @unimplemented
*/
HBRUSH
APIENTRY
NtGdiSetBrushAttributes(
IN HBRUSH hbm,
IN DWORD dwFlags)
{
UNIMPLEMENTED;
return NULL;
}
/*
* @unimplemented
*/
HBRUSH
APIENTRY
NtGdiClearBrushAttributes(
IN HBRUSH hbr,
IN DWORD dwFlags)
{
UNIMPLEMENTED;
return NULL;
}
/* EOF */

View file

@ -0,0 +1,550 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS win32 subsystem
* PURPOSE: BRUSH class implementation
* PROGRAMER: Timo Kreuzer (timo.kreuzer@reactos.org)
*
* REFERENCES: http://support.microsoft.com/kb/kbview/108497
*/
#include "brush.hpp"
DBG_DEFAULT_CHANNEL(GdiBrush);
BRUSH::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)
: BASEOBJECT(loobjtype)
{
static ULONG ulGlobalBrushUnique = 0;
/* Get a unique value */
this->ulBrushUnique = InterlockedIncrementUL(&ulGlobalBrushUnique);
/* Start with kmode brush attribute */
this->pBrushAttr = &this->BrushAttr;
/* Set parameters */
this->flAttrs = flAttrs;
this->iHatch = iHatch;
this->hbmPattern = hbmPattern;
this->hbmClient = (HBITMAP)pvClient;
this->pBrushAttr->lbColor = crColor;
/* Initialize the other fields */
this->ptOrigin.x = 0;
this->ptOrigin.y = 0;
this->bCacheGrabbed = FALSE;
this->crBack = 0;
this->crFore = 0;
this->ulPalTime = 0;
this->ulSurfTime = 0;
this->pvRBrush = NULL;
this->hdev = NULL;
}
BRUSH::~BRUSH(
VOID)
{
/* Check if we have a user mode brush attribute */
if (this->pBrushAttr != &this->BrushAttr)
{
/* Free memory to the process GDI pool */
GdiPoolFree(GetBrushAttrPool(), this->pBrushAttr);
}
/* Delete the pattern bitmap */
if (this->hbmPattern != NULL)
{
GreSetBitmapOwner(this->hbmPattern, BASEOBJECT::OWNER::POWNED);
GreDeleteObject(this->hbmPattern);
}
}
VOID
BRUSH::vDeleteObject(
_In_ PVOID pvObject)
{
PBRUSH pbr = static_cast<PBRUSH>(pvObject);
NT_ASSERT((GDI_HANDLE_GET_TYPE(pbr->hHmgr()) == GDILoObjType_LO_BRUSH_TYPE) ||
(GDI_HANDLE_GET_TYPE(pbr->hHmgr()) == GDILoObjType_LO_PEN_TYPE) ||
(GDI_HANDLE_GET_TYPE(pbr->hHmgr()) == GDILoObjType_LO_EXTPEN_TYPE));
delete pbr;
}
BOOL
BRUSH::bAllocateBrushAttr(
VOID)
{
PBRUSH_ATTR pBrushAttr;
NT_ASSERT(this->pBrushAttr == &this->BrushAttr);
/* Allocate a brush attribute from the pool */
pBrushAttr = static_cast<PBRUSH_ATTR>(GdiPoolAllocate(GetBrushAttrPool()));
if (pBrushAttr == NULL)
{
ERR("Could not allocate brush attr\n");
return FALSE;
}
/* Copy the content from the kernel mode brush attribute */
this->pBrushAttr = pBrushAttr;
*this->pBrushAttr = this->BrushAttr;
/* Set the object attribute in the handle table */
vSetObjectAttr(pBrushAttr);
return TRUE;
}
VOID
BRUSH::vSetSolidColor(
_In_ COLORREF crColor)
{
NT_ASSERT(this->flAttrs & BR_IS_SOLID);
/* Set new color and reset the pal times */
this->pBrushAttr->lbColor = crColor & 0xFFFFFF;
this->ulPalTime = -1;
this->ulSurfTime = -1;
}
HBITMAP
BRUSH::hbmGetBitmapHandle(
_Out_ PUINT puUsage) const
{
/* Return the color usage based on flags */
*puUsage = (this->flAttrs & BR_IS_DIBPALCOLORS) ? DIB_PAL_COLORS :
(this->flAttrs & BR_IS_DIBPALINDICES) ? DIB_PAL_INDICES :
DIB_RGB_COLORS;
return this->hbmPattern;
}
UINT
BRUSH::cjGetObject(
_In_ UINT cjSize,
_Out_bytecap_(cjSize) PLOGBRUSH plb) const
{
/* Check if only size is requested */
if (plb == NULL)
return sizeof(LOGBRUSH);
/* Check if size is ok */
if (cjSize == 0)
return 0;
/* Set color */
plb->lbColor = this->BrushAttr.lbColor;
/* Set style and hatch based on the attribute flags */
if (this->flAttrs & BR_IS_SOLID)
{
plb->lbStyle = BS_SOLID;
plb->lbHatch = 0;
}
else if (this->flAttrs & BR_IS_HATCH)
{
plb->lbStyle = BS_HATCHED;
plb->lbHatch = this->iHatch;
}
else if (this->flAttrs & BR_IS_DIB)
{
plb->lbStyle = BS_DIBPATTERN;
plb->lbHatch = (ULONG_PTR)this->hbmClient;
}
else if (this->flAttrs & BR_IS_BITMAP)
{
plb->lbStyle = BS_PATTERN;
plb->lbHatch = (ULONG_PTR)this->hbmClient;
}
else if (this->flAttrs & BR_IS_NULL)
{
plb->lbStyle = BS_NULL;
plb->lbHatch = 0;
}
else
{
NT_ASSERT(FALSE);
}
return sizeof(LOGBRUSH);
}
static
HBRUSH
CreateBrushInternal(
_In_ ULONG flAttrs,
_In_ COLORREF crColor,
_In_ ULONG iHatch,
_In_opt_ HBITMAP hbmPattern,
_In_opt_ PVOID pvClient)
{
BASEOBJECT::OWNER owner;
PBRUSH pbr;
HBRUSH hbr;
NT_ASSERT(((flAttrs & BR_IS_BITMAP) == 0) || (hbmPattern != NULL));
/* Create the brush (brush takes ownership of the bitmap) */
pbr = new BRUSH(flAttrs, crColor, iHatch, hbmPattern, pvClient);
if (pbr == NULL)
{
ERR("Failed to allocate a brush\n");
GreSetBitmapOwner(hbmPattern, BASEOBJECT::OWNER::POWNED);
GreDeleteObject(hbmPattern);
return NULL;
}
/* Check if this is a global brush */
if (!(flAttrs & BR_IS_GLOBAL))
{
/* Not a global brush, so allocate a user mode brush attribute */
if (!pbr->bAllocateBrushAttr())
{
ERR("Failed to allocate brush attribute\n");
delete pbr;
return NULL;
}
}
/* Set the owner, either public or process owned */
owner = (flAttrs & BR_IS_GLOBAL) ? BASEOBJECT::OWNER::PUBLIC :
BASEOBJECT::OWNER::POWNED;
/* Insert the object into the GDI handle table */
hbr = static_cast<HBRUSH>(pbr->hInsertObject(owner));
if (hbr == NULL)
{
ERR("Failed to insert brush\n");
delete pbr;
return NULL;
}
/* Unlock the brush */
pbr->vUnlock();
return hbr;
}
/* C interface ***************************************************************/
extern "C" {
VOID
NTAPI
BRUSH_vDeleteObject(
PVOID pvObject)
{
BRUSH::vDeleteObject(pvObject);
}
INT
FASTCALL
BRUSH_GetObject(
PBRUSH pbr,
INT cjBuffer,
LPLOGBRUSH plbBuffer)
{
return pbr->cjGetObject(cjBuffer, plbBuffer);
}
HBRUSH
NTAPI
IntGdiCreateNullBrush(
VOID)
{
/* Call the internal function */
return CreateBrushInternal(BR_IS_NULL | BR_IS_GLOBAL, 0, 0, NULL, NULL);
}
HBRUSH
APIENTRY
IntGdiCreateSolidBrush(
COLORREF crColor)
{
/* Call the internal function */
return CreateBrushInternal(BR_IS_SOLID | BR_IS_GLOBAL,
crColor,
0,
NULL,
NULL);
}
HBRUSH
NTAPI
IntGdiCreatePatternBrush(
HBITMAP hbmPattern)
{
NT_ASSERT(hbmPattern != NULL);
GreSetBitmapOwner(hbmPattern, BASEOBJECT::OWNER::PUBLIC);
return CreateBrushInternal(BR_IS_BITMAP | BR_IS_GLOBAL,
0,
0,
hbmPattern,
NULL);
}
VOID
NTAPI
IntGdiSetSolidBrushColor(
_In_ HBRUSH hbr,
_In_ COLORREF crColor)
{
PBRUSH pbr;
/* Lock the brush */
pbr = BRUSH::LockAny(hbr);
if (pbr == NULL)
{
ERR("Failed to lock brush %p\n", hbr);
return;
}
/* Call the member function */
pbr->vSetSolidColor(crColor);
/* Unlock the brush */
pbr->vUnlock();
}
__kernel_entry
HBRUSH
APIENTRY
NtGdiCreateSolidBrush(
_In_ COLORREF crColor,
_In_opt_ HBRUSH hbr)
{
if (hbr != NULL)
{
WARN("hbr is not supported, ignoring\n");
}
/* Call the internal function */
return CreateBrushInternal(BR_IS_SOLID, crColor, 0, NULL, NULL);
}
__kernel_entry
HBRUSH
APIENTRY
NtGdiCreateHatchBrushInternal(
_In_ ULONG iHatch,
_In_ COLORREF crColor,
_In_ BOOL bPen)
{
FLONG flAttr;
if (bPen)
{
WARN("bPen is not supported, ignoring\n");
}
/* Check what kind if hatch style this is */
if (iHatch < HS_DDI_MAX)
{
flAttr = BR_IS_HATCH;
}
else if (iHatch < HS_API_MAX)
{
flAttr = BR_IS_SOLID;
}
else
{
ERR("Invalid iHatch: %lu\n", iHatch);
return NULL;
}
/* Call the internal function */
return CreateBrushInternal(flAttr, crColor, iHatch, NULL, NULL);
}
__kernel_entry
HBRUSH
APIENTRY
NtGdiCreatePatternBrushInternal(
_In_ HBITMAP hbmClient,
_In_ BOOL bPen,
_In_ BOOL b8X8)
{
HBITMAP hbmPattern;
if (b8X8)
{
WARN("b8X8 is not supported, ignoring\n");
}
if (bPen)
{
WARN("bPen is not supported, ignoring\n");
}
/* Copy the bitmap */
hbmPattern = BITMAP_CopyBitmap(hbmClient);
if (hbmPattern == NULL)
{
ERR("Failed to copy the bitmap %p\n", hbmPattern);
return NULL;
}
/* Call the internal function (will delete hbmPattern on failure) */
return CreateBrushInternal(BR_IS_BITMAP, 0, 0, hbmPattern, hbmClient);
}
__kernel_entry
HBRUSH
APIENTRY
NtGdiCreateDIBBrush(
_In_reads_bytes_(cj) PVOID pv,
_In_ FLONG uUsage,
_In_ UINT cj,
_In_ BOOL b8X8,
_In_ BOOL bPen,
_In_ PVOID pvClient)
{
PVOID pvPackedDIB;
FLONG flAttrs;
HBITMAP hbm;
HBRUSH hbr = NULL;
if (b8X8)
{
WARN("b8X8 is not supported, ignoring\n");
}
if (bPen)
{
WARN("bPen is not supported, ignoring\n");
}
if (uUsage > DIB_PAL_INDICES)
{
ERR("Invalid uUsage value: %lu\n", uUsage);
EngSetLastError(ERROR_INVALID_PARAMETER);
return NULL;
}
/* Allocate a buffer for the packed DIB */
pvPackedDIB = ExAllocatePoolWithTag(PagedPool, cj, GDITAG_TEMP);
if (pvPackedDIB == NULL)
{
ERR("Failed to allocate temp buffer of %u bytes\n", cj);
return NULL;
}
/* Probe and copy the packed DIB */
_SEH2_TRY
{
ProbeForRead(pv, cj, 1);
RtlCopyMemory(pvPackedDIB, pv, cj);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
ERR("Got exception, pv = %p, cj = %lu\n", pv, cj);
goto cleanup;
}
_SEH2_END;
flAttrs = BR_IS_BITMAP | BR_IS_DIB;
/* Check what kind of color table we have */
if (uUsage == DIB_PAL_COLORS)
{
/* Remember it and use DIB_PAL_BRUSHHACK to create a "special" palette */
flAttrs |= BR_IS_DIBPALCOLORS;
uUsage = DIB_PAL_BRUSHHACK;
}
else if (uUsage == DIB_PAL_INDICES)
{
/* No color table, bitmap contains device palette indices */
flAttrs |= BR_IS_DIBPALINDICES;
/* FIXME: This makes tests pass, but needs investigation. */
flAttrs |= BR_IS_NULL;
}
/* Create a bitmap from the DIB */
hbm = GreCreateDIBitmapFromPackedDIB(pvPackedDIB, cj, uUsage);
if (hbm == NULL)
{
ERR("Failed to create bitmap from DIB\n");
goto cleanup;
}
/* Call the internal function (will delete hbm on failure) */
hbr = CreateBrushInternal(flAttrs, 0, 0, hbm, pvClient);
cleanup:
ExFreePoolWithTag(pvPackedDIB, GDITAG_TEMP);
return hbr;
}
__kernel_entry
HBITMAP
APIENTRY
NtGdiGetObjectBitmapHandle(
_In_ HBRUSH hbr,
_Out_ UINT *piUsage)
{
PBRUSH pbr;
HBITMAP hbm;
UINT uUsage;
/* Lock the brush */
pbr = BRUSH::LockForRead(hbr);
if (pbr == NULL)
{
ERR("Failed to lock brush %p\n", hbr);
return NULL;
}
/* Call the member function */
hbm = pbr->hbmGetBitmapHandle(&uUsage);
/* Unlock the brush */
pbr->vUnlock();
_SEH2_TRY
{
ProbeForWrite(piUsage, sizeof(*piUsage), 1);
*piUsage = uUsage;
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
ERR("Got exception! piUsage = %p\n", piUsage);
hbm = NULL;
}
_SEH2_END;
return hbm;
}
__kernel_entry
HBRUSH
APIENTRY
NtGdiSetBrushAttributes(
_In_ HBRUSH hbr,
_In_ DWORD dwFlags)
{
__debugbreak();
return NULL;
}
__kernel_entry
HBRUSH
APIENTRY
NtGdiClearBrushAttributes(
_In_ HBRUSH hbr,
_In_ DWORD dwFlags)
{
__debugbreak();
return NULL;
}
} /* extern "C" */

View file

@ -0,0 +1,121 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS win32 subsystem
* PURPOSE: BRUSH class definition
* PROGRAMER: Timo Kreuzer (timo.kreuzer@reactos.org)
*/
#pragma once
#include <win32k.h>
#include "baseobj.hpp"
__prefast_operator_new_null
class BRUSH : public BASEOBJECT, protected _BRUSHBODY
{
public:
_Analysis_mode_(_Analysis_operator_new_null_)
inline
void*
__cdecl
operator new(
_In_ size_t cjSize) throw()
{
return ExAllocatePoolWithTag(PagedPool, cjSize, GDITAG_HMGR_BRUSH_TYPE);
//return BASEOBJECT::pvAllocate(GDIObjType_BRUSH_TYPE, cjSize);
}
inline
void
operator delete(
void *pvObject)
{
/// HACK! better would be to extract the exact object type's tag
ExFreePool(pvObject);
//ExFreePoolWithTag(pvObject, GDITAG_HMGR_BRUSH_TYPE);
//BASEOBJECT::pvFree(GDIObjType_BRUSH_TYPE, cjSize);
}
BRUSH(
_In_ FLONG flAttrs,
_In_ COLORREF crColor,
_In_ ULONG iHatch,
_In_opt_ HBITMAP hbmPattern,
_In_opt_ PVOID pvClient,
_In_ GDILOOBJTYPE objtype);
~BRUSH(
VOID);
static
VOID
vDeleteObject(
_In_ PVOID pvObject);
BOOL
bAllocateBrushAttr(
VOID);
_Check_return_
_Ret_opt_bytecount_(sizeof(BRUSH))
static
inline
PBRUSH
LockForRead(
_In_ HBRUSH hbr)
{
return static_cast<PBRUSH>(
BASEOBJECT::LockShared(hbr,
GDILoObjType_LO_BRUSH_TYPE,
BASEOBJECT::OWNER::PUBLIC));
}
_Check_return_
_Ret_opt_bytecount_(sizeof(BRUSH))
static
inline
PBRUSH
LockForWrite(
_In_ HBRUSH hbr)
{
return static_cast<PBRUSH>(
BASEOBJECT::LockShared(hbr,
GDILoObjType_LO_BRUSH_TYPE,
BASEOBJECT::OWNER::POWNED));
}
_Check_return_
_Ret_opt_bytecap_(sizeof(BRUSH))
static
inline
PBRUSH
LockAny(
_In_ HBRUSH hbr)
{
return static_cast<PBRUSH>(
BASEOBJECT::LockShared(hbr,
GDILoObjType_LO_BRUSH_TYPE,
BASEOBJECT::OWNER::NONE));
}
UINT
cjGetObject(
_In_ UINT cjBuffer,
_Out_bytecap_(cjBuffer) PLOGBRUSH plbBuffer) const;
HBITMAP
hbmGetBitmapHandle(
_Out_ PUINT puUsage) const;
VOID
vSetSolidColor(
_In_ COLORREF crColor);
};
/* HACK! */
extern "C"
PGDI_POOL
GetBrushAttrPool(VOID);

View file

@ -29,6 +29,19 @@
* object from being locked by another thread. A shared lock will simply fail,
* while an exclusive lock will succeed after the object was unlocked.
*
* Ownership:
*
* Owner: POWNED PUBLIC NONE spec
* ---------------------------------------------------
* LockForRead + + - PUBLIC
* LockForWrite + - - POWNED
* LockAny + + + NONE
* NtGdiDeleteObjectApp + - - PUBLIC
* GreDeleteObject + + + NONE
* GreSetOwner(POWNED) - - + -
* GreSetOwner(PUBLIC) + - + -
* GreSetOwner(NONE) + - - -
*
*/
/* INCLUDES ******************************************************************/
@ -1590,5 +1603,16 @@ GDI_CleanupForProcess(struct _EPROCESS *Process)
return TRUE;
}
/// HACK!
PGDI_POOL
GetBrushAttrPool(VOID)
{
PPROCESSINFO ppi;
ppi = PsGetCurrentProcessWin32Process();
NT_ASSERT(ppi != NULL);
return ppi->pPoolBrushAttr;
}
/* EOF */

View file

@ -66,6 +66,10 @@ typedef struct _SECURITY_ATTRIBUTES SECURITY_ATTRIBUTES, *LPSECURITY_ATTRIBUTES;
/* SEH support with PSEH */
#include <pseh/pseh2.h>
#ifdef __cplusplus
extern "C" {
#endif
/* Public Win32K headers */
#include <include/ntgdityp.h>
#include <ntgdi.h>
@ -91,4 +95,8 @@ typedef struct _SECURITY_ATTRIBUTES SECURITY_ATTRIBUTES, *LPSECURITY_ATTRIBUTES;
/* Internal Win32K header */
#include "win32kp.h"
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* __W32K_H */

View file

@ -144,9 +144,14 @@ UserInitialize(VOID)
if (gpsi->hbrGray == NULL)
{
hPattern55AABitmap = GreCreateBitmap(8, 8, 1, 1, (LPBYTE)wPattern55AA);
if (hPattern55AABitmap == NULL)
return STATUS_INSUFFICIENT_RESOURCES;
//NT_VERIFY(GreSetBitmapOwner(hPattern55AABitmap, GDI_OBJ_HMGR_PUBLIC));
gpsi->hbrGray = IntGdiCreatePatternBrush(hPattern55AABitmap);
GreDeleteObject(hPattern55AABitmap);
GreSetBrushOwner(gpsi->hbrGray, GDI_OBJ_HMGR_PUBLIC);
if (gpsi->hbrGray == NULL)
return STATUS_INSUFFICIENT_RESOURCES;
}
return STATUS_SUCCESS;