[WIN32K]
authorTimo Kreuzer <timo.kreuzer@reactos.org>
Wed, 25 Mar 2015 22:38:20 +0000 (22:38 +0000)
committerTimo Kreuzer <timo.kreuzer@reactos.org>
Wed, 25 Mar 2015 22:38:20 +0000 (22:38 +0000)
Rewrite brush code in C++

svn path=/trunk/; revision=66893

reactos/win32ss/CMakeLists.txt
reactos/win32ss/gdi/ntgdi/baseobj.hpp [new file with mode: 0644]
reactos/win32ss/gdi/ntgdi/brush.c [deleted file]
reactos/win32ss/gdi/ntgdi/brush.cpp [new file with mode: 0644]
reactos/win32ss/gdi/ntgdi/brush.hpp [new file with mode: 0644]
reactos/win32ss/gdi/ntgdi/gdiobj.c
reactos/win32ss/pch.h
reactos/win32ss/user/ntuser/ntuser.c

index f85a243..88c74d2 100644 (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)
diff --git a/reactos/win32ss/gdi/ntgdi/baseobj.hpp b/reactos/win32ss/gdi/ntgdi/baseobj.hpp
new file mode 100644 (file)
index 0000000..f01b462
--- /dev/null
@@ -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 (file)
index 7d8bb6d..0000000
+++ /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 <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 */
diff --git a/reactos/win32ss/gdi/ntgdi/brush.cpp b/reactos/win32ss/gdi/ntgdi/brush.cpp
new file mode 100644 (file)
index 0000000..1049684
--- /dev/null
@@ -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" */
diff --git a/reactos/win32ss/gdi/ntgdi/brush.hpp b/reactos/win32ss/gdi/ntgdi/brush.hpp
new file mode 100644 (file)
index 0000000..4fea65e
--- /dev/null
@@ -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);
index 594f14b..c7968c5 100644 (file)
  *   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 */
index 9c22f00..ebedadc 100644 (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 */
index 03870af..3982e78 100644 (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;