From 976a3274ad1c133b23dc9bd0b519b8c58d883fe1 Mon Sep 17 00:00:00 2001 From: Timo Kreuzer Date: Wed, 25 Mar 2015 22:38:20 +0000 Subject: [PATCH] [WIN32K] Rewrite brush code in C++ svn path=/trunk/; revision=66893 --- reactos/win32ss/CMakeLists.txt | 9 +- reactos/win32ss/gdi/ntgdi/baseobj.hpp | 109 +++++ reactos/win32ss/gdi/ntgdi/brush.c | 563 -------------------------- reactos/win32ss/gdi/ntgdi/brush.cpp | 550 +++++++++++++++++++++++++ reactos/win32ss/gdi/ntgdi/brush.hpp | 121 ++++++ reactos/win32ss/gdi/ntgdi/gdiobj.c | 24 ++ reactos/win32ss/pch.h | 8 + reactos/win32ss/user/ntuser/ntuser.c | 7 +- 8 files changed, 825 insertions(+), 566 deletions(-) create mode 100644 reactos/win32ss/gdi/ntgdi/baseobj.hpp delete mode 100644 reactos/win32ss/gdi/ntgdi/brush.c create mode 100644 reactos/win32ss/gdi/ntgdi/brush.cpp create mode 100644 reactos/win32ss/gdi/ntgdi/brush.hpp diff --git a/reactos/win32ss/CMakeLists.txt b/reactos/win32ss/CMakeLists.txt index f85a2430a49..88c74d2f88d 100644 --- a/reactos/win32ss/CMakeLists.txt +++ b/reactos/win32ss/CMakeLists.txt @@ -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) diff --git a/reactos/win32ss/gdi/ntgdi/baseobj.hpp b/reactos/win32ss/gdi/ntgdi/baseobj.hpp new file mode 100644 index 00000000000..f01b4628e7c --- /dev/null +++ b/reactos/win32ss/gdi/ntgdi/baseobj.hpp @@ -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); + } + +}; + + diff --git a/reactos/win32ss/gdi/ntgdi/brush.c b/reactos/win32ss/gdi/ntgdi/brush.c deleted file mode 100644 index 7d8bb6d1207..00000000000 --- a/reactos/win32ss/gdi/ntgdi/brush.c +++ /dev/null @@ -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 - -#define NDEBUG -#include - -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 */ diff --git a/reactos/win32ss/gdi/ntgdi/brush.cpp b/reactos/win32ss/gdi/ntgdi/brush.cpp new file mode 100644 index 00000000000..1049684aade --- /dev/null +++ b/reactos/win32ss/gdi/ntgdi/brush.cpp @@ -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(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(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(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" */ diff --git a/reactos/win32ss/gdi/ntgdi/brush.hpp b/reactos/win32ss/gdi/ntgdi/brush.hpp new file mode 100644 index 00000000000..4fea65ea3c2 --- /dev/null +++ b/reactos/win32ss/gdi/ntgdi/brush.hpp @@ -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 +#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( + 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( + 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( + 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); diff --git a/reactos/win32ss/gdi/ntgdi/gdiobj.c b/reactos/win32ss/gdi/ntgdi/gdiobj.c index 594f14b9985..c7968c58f6f 100644 --- a/reactos/win32ss/gdi/ntgdi/gdiobj.c +++ b/reactos/win32ss/gdi/ntgdi/gdiobj.c @@ -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 */ diff --git a/reactos/win32ss/pch.h b/reactos/win32ss/pch.h index 9c22f009267..ebedadc942d 100644 --- a/reactos/win32ss/pch.h +++ b/reactos/win32ss/pch.h @@ -66,6 +66,10 @@ typedef struct _SECURITY_ATTRIBUTES SECURITY_ATTRIBUTES, *LPSECURITY_ATTRIBUTES; /* SEH support with PSEH */ #include +#ifdef __cplusplus +extern "C" { +#endif + /* Public Win32K headers */ #include #include @@ -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 */ diff --git a/reactos/win32ss/user/ntuser/ntuser.c b/reactos/win32ss/user/ntuser/ntuser.c index 03870af84f1..3982e78ae1c 100644 --- a/reactos/win32ss/user/ntuser/ntuser.c +++ b/reactos/win32ss/user/ntuser/ntuser.c @@ -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;