Author: fireball
Date: Sun Aug  2 22:53:12 2009
New Revision: 42348

URL: http://svn.reactos.org/svn/reactos?rev=42348&view=rev
Log:
- Create stock bitmap in win32k and use it whenever a stock bitmap is selected 
into the DC.
- Bring in GDIOBJ_ConvertToStockObj from trunk.
- Fixes arwinss issue nr. 7.

Modified:
    branches/arwinss/reactos/dll/win32/winent.drv/gdidrv.c
    branches/arwinss/reactos/include/psdk/ntrosgdi.h
    branches/arwinss/reactos/subsystems/win32/win32k/gdi/bitmap.c
    branches/arwinss/reactos/subsystems/win32/win32k/gdi/dc.c
    branches/arwinss/reactos/subsystems/win32/win32k/gre/gdiobj.c
    branches/arwinss/reactos/subsystems/win32/win32k/include/gre.h
    branches/arwinss/reactos/subsystems/win32/win32k/main/init.c
    branches/arwinss/reactos/subsystems/win32/win32k/w32ksvc.db

Modified: branches/arwinss/reactos/dll/win32/winent.drv/gdidrv.c
URL: 
http://svn.reactos.org/svn/reactos/branches/arwinss/reactos/dll/win32/winent.drv/gdidrv.c?rev=42348&r1=42347&r2=42348&view=diff
==============================================================================
--- branches/arwinss/reactos/dll/win32/winent.drv/gdidrv.c [iso-8859-1] 
(original)
+++ branches/arwinss/reactos/dll/win32/winent.drv/gdidrv.c [iso-8859-1] Sun Aug 
 2 22:53:12 2009
@@ -19,6 +19,9 @@
 #include "wine/debug.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(rosgdidrv);
+
+/* GLOBALS ****************************************************************/
+HANDLE hStockBitmap;
 
 /* FUNCTIONS **************************************************************/
 
@@ -123,6 +126,10 @@
         hKernelDC = (*pdev)->hKernelDC;
     else
         hKernelDC = 0;
+
+    /* Save stock bitmap's handle */
+    if (dcInfo.dwType == OBJ_MEMDC && !hStockBitmap)
+        hStockBitmap = GetCurrentObject( hdc, OBJ_BITMAP );
 
     /* Call the win32 kernel */
     bRet = RosGdiCreateDC(&dcInfo, &hKernelDC, driver, device, output, 
initData);
@@ -453,8 +460,18 @@
 
 HBITMAP CDECL RosDrv_SelectBitmap( NTDRV_PDEVICE *physDev, HBITMAP hbitmap )
 {
-    RosGdiSelectBitmap(physDev->hKernelDC, hbitmap);
-
+    BOOL bRes, bStock = FALSE;
+
+    /* Check if it's a stock bitmap */
+    if (hbitmap == hStockBitmap) bStock = TRUE;
+
+    /* Select the bitmap into the DC */
+    bRes = RosGdiSelectBitmap(physDev->hKernelDC, hbitmap, bStock);
+
+    /* If there was an error, return 0 */
+    if (!bRes) return 0;
+
+    /* Return handle of selected bitmap as a success*/
     return hbitmap;
 }
 

Modified: branches/arwinss/reactos/include/psdk/ntrosgdi.h
URL: 
http://svn.reactos.org/svn/reactos/branches/arwinss/reactos/include/psdk/ntrosgdi.h?rev=42348&r1=42347&r2=42348&view=diff
==============================================================================
--- branches/arwinss/reactos/include/psdk/ntrosgdi.h [iso-8859-1] (original)
+++ branches/arwinss/reactos/include/psdk/ntrosgdi.h [iso-8859-1] Sun Aug  2 
22:53:12 2009
@@ -101,7 +101,7 @@
 BOOL APIENTRY RosGdiDeleteDC( HDC physDev );
 BOOL APIENTRY RosGdiGetDCOrgEx( HDC physDev, LPPOINT lpp );
 BOOL APIENTRY RosGdiPaintRgn( HDC physDev, HRGN hrgn );
-VOID APIENTRY RosGdiSelectBitmap( HDC physDev, HBITMAP hbitmap );
+BOOL APIENTRY RosGdiSelectBitmap( HDC physDev, HBITMAP hbitmap, BOOL stock );
 VOID APIENTRY RosGdiSelectBrush( HDC physDev, LOGBRUSH *pLogBrush );
 HFONT APIENTRY RosGdiSelectFont( HDC physDev, HFONT hfont, HANDLE gdiFont );
 VOID APIENTRY RosGdiSelectPen( HDC physDev, LOGPEN *pLogPen, EXTLOGPEN 
*pExtLogPen );

Modified: branches/arwinss/reactos/subsystems/win32/win32k/gdi/bitmap.c
URL: 
http://svn.reactos.org/svn/reactos/branches/arwinss/reactos/subsystems/win32/win32k/gdi/bitmap.c?rev=42348&r1=42347&r2=42348&view=diff
==============================================================================
--- branches/arwinss/reactos/subsystems/win32/win32k/gdi/bitmap.c [iso-8859-1] 
(original)
+++ branches/arwinss/reactos/subsystems/win32/win32k/gdi/bitmap.c [iso-8859-1] 
Sun Aug  2 22:53:12 2009
@@ -11,6 +11,9 @@
 #include <win32k.h>
 #define NDEBUG
 #include <debug.h>
+
+/* GLOBALS *******************************************************************/
+HGDIOBJ hStockBmp;
 
 /* PUBLIC FUNCTIONS **********************************************************/
 
@@ -293,5 +296,17 @@
     return bRet;
 }
 
+VOID
+CreateStockBitmap()
+{
+    SIZE slSize;
+
+    /* Create 1x1 bitmap */
+    slSize.cx = 1; slSize.cy = 1;
+    hStockBmp = GreCreateBitmap(slSize, 1, 1, 0, NULL);
+
+    /* Convert it to a stock object */
+    GDIOBJ_ConvertToStockObj(&hStockBmp);
+}
 
 /* EOF */

Modified: branches/arwinss/reactos/subsystems/win32/win32k/gdi/dc.c
URL: 
http://svn.reactos.org/svn/reactos/branches/arwinss/reactos/subsystems/win32/win32k/gdi/dc.c?rev=42348&r1=42347&r2=42348&view=diff
==============================================================================
--- branches/arwinss/reactos/subsystems/win32/win32k/gdi/dc.c [iso-8859-1] 
(original)
+++ branches/arwinss/reactos/subsystems/win32/win32k/gdi/dc.c [iso-8859-1] Sun 
Aug  2 22:53:12 2009
@@ -185,21 +185,26 @@
     return FALSE;
 }
 
-VOID APIENTRY RosGdiSelectBitmap( HDC physDev, HBITMAP hbitmap )
+BOOL APIENTRY RosGdiSelectBitmap( HDC physDev, HBITMAP hbitmap, BOOL bStock )
 {
     PDC pDC;
     PSURFACE pSurface;
     HGDIOBJ hBmpKern;
-    SIZEL slSize;
-
-    hBmpKern = GDI_MapUserHandle(hbitmap);
-    if (!hBmpKern)
-    {
-        DPRINT1("Trying to select an unknown bitmap %x to the DC %x!\n", 
hbitmap, physDev);
-
-        /* It probably is a stock bitmap, so select it */
-        slSize.cx = 1; slSize.cy = 1;
-        hBmpKern = GreCreateBitmap(slSize, 1, 1, 0, NULL);
+
+    if (bStock)
+    {
+        /* Selecting stock bitmap */
+        hBmpKern = hStockBmp;
+    }
+    else
+    {
+        /* Selecting usual bitmap */
+        hBmpKern = GDI_MapUserHandle(hbitmap);
+        if (!hBmpKern)
+        {
+            DPRINT1("Trying to select an unknown bitmap %x to the DC %x!\n", 
hbitmap, physDev);
+            return FALSE;
+        }
     }
 
     DPRINT("Selecting %x bitmap to hdc %x\n", hBmpKern, physDev);
@@ -220,6 +225,8 @@
 
     /* Release the DC object */
     DC_Unlock(pDC);
+
+    return TRUE;
 }
 
 VOID APIENTRY RosGdiSelectBrush( HDC physDev, LOGBRUSH *pLogBrush )

Modified: branches/arwinss/reactos/subsystems/win32/win32k/gre/gdiobj.c
URL: 
http://svn.reactos.org/svn/reactos/branches/arwinss/reactos/subsystems/win32/win32k/gre/gdiobj.c?rev=42348&r1=42347&r2=42348&view=diff
==============================================================================
--- branches/arwinss/reactos/subsystems/win32/win32k/gre/gdiobj.c [iso-8859-1] 
(original)
+++ branches/arwinss/reactos/subsystems/win32/win32k/gre/gdiobj.c [iso-8859-1] 
Sun Aug  2 22:53:12 2009
@@ -1050,6 +1050,139 @@
 }
 
 BOOL APIENTRY
+GDIOBJ_ConvertToStockObj(HGDIOBJ *phObj)
+{
+    /*
+     * FIXME !!!!! THIS FUNCTION NEEDS TO BE FIXED - IT IS NOT SAFE WHEN OTHER 
THREADS
+     *             MIGHT ATTEMPT TO LOCK THE OBJECT DURING THIS CALL!!!
+     */
+    PGDI_TABLE_ENTRY Entry;
+    HANDLE ProcessId, LockedProcessId, PrevProcId;
+    PTHREADINFO Thread;
+    HGDIOBJ hObj;
+
+    GDIDBG_INITLOOPTRACE();
+
+    ASSERT(phObj);
+    hObj = *phObj;
+
+    DPRINT("GDIOBJ_ConvertToStockObj: hObj: 0x%08x\n", hObj);
+
+    Thread = PsGetCurrentThreadWin32Thread();
+
+    if (!GDI_HANDLE_IS_STOCKOBJ(hObj))
+    {
+        ProcessId = PsGetCurrentProcessId();
+        LockedProcessId = (HANDLE)((ULONG_PTR)ProcessId | 0x1);
+
+        Entry = GDI_HANDLE_GET_ENTRY(GdiHandleTable, hObj);
+
+LockHandle:
+        /* lock the object, we must not convert stock objects, so don't 
check!!! */
+        PrevProcId = 
InterlockedCompareExchangePointer((PVOID*)&Entry->ProcessId, LockedProcessId, 
ProcessId);
+        if (PrevProcId == ProcessId)
+        {
+            LONG NewType, PrevType, OldType;
+
+            /* we're locking an object that belongs to our process. First 
calculate
+               the new object type including the stock object flag and then 
try to
+               exchange it.*/
+            /* On Windows the higher 16 bit of the type field don't contain the
+               full type from the handle, but the base type.
+               (type = BRSUH, PEN, EXTPEN, basetype = BRUSH) */
+            OldType = ((ULONG)hObj & GDI_HANDLE_BASETYPE_MASK) | ((ULONG)hObj 
>> GDI_ENTRY_UPPER_SHIFT);
+            /* We are currently not using bits 24..31 (flags) of the type 
field, but for compatibility
+               we copy them as we can't get them from the handle */
+            OldType |= Entry->Type & GDI_ENTRY_FLAGS_MASK;
+
+            /* As the object should be a stock object, set it's flag, but only 
in the lower 16 bits */
+            NewType = OldType | GDI_ENTRY_STOCK_MASK;
+
+            /* Try to exchange the type field - but only if the old (previous 
type) matches! */
+            PrevType = InterlockedCompareExchange(&Entry->Type, NewType, 
OldType);
+            if (PrevType == OldType && Entry->KernelData != NULL)
+            {
+                PTHREADINFO PrevThread;
+                PBASEOBJECT Object;
+
+                /* We successfully set the stock object flag.
+                   KernelData should never be NULL here!!! */
+                ASSERT(Entry->KernelData);
+
+                Object = Entry->KernelData;
+
+                PrevThread = Object->Tid;
+                if (Object->cExclusiveLock == 0 || PrevThread == Thread)
+                {
+                    /* dereference the process' object counter */
+                    if (PrevProcId != GDI_GLOBAL_PROCESS)
+                    {
+                        PEPROCESS OldProcess;
+                        PPROCESSINFO W32Process;
+                        NTSTATUS Status;
+
+                        /* FIXME */
+                        Status = 
PsLookupProcessByProcessId((HANDLE)((ULONG_PTR)PrevProcId & ~0x1), &OldProcess);
+                        if (NT_SUCCESS(Status))
+                        {
+                            W32Process = 
(PPROCESSINFO)OldProcess->Win32Process;
+                            if (W32Process != NULL)
+                            {
+                                
InterlockedDecrement(&W32Process->GDIHandleCount);
+                            }
+                            ObDereferenceObject(OldProcess);
+                        }
+                    }
+
+                    hObj = (HGDIOBJ)((ULONG)(hObj) | GDI_HANDLE_STOCK_MASK);
+                    *phObj = hObj;
+                    Object->hHmgr = hObj;
+
+                    /* remove the process id lock and make it global */
+                    
(void)InterlockedExchangePointer((PVOID*)&Entry->ProcessId, GDI_GLOBAL_PROCESS);
+
+                    /* we're done, successfully converted the object */
+                    return TRUE;
+                }
+                else
+                {
+                    GDIDBG_TRACELOOP(hObj, PrevThread, Thread);
+
+                    /* WTF?! The object is already locked by a different 
thread!
+                       Release the lock, wait a bit and try again!
+                       FIXME - we should give up after some time unless we 
want to wait forever! */
+                    
(void)InterlockedExchangePointer((PVOID*)&Entry->ProcessId, PrevProcId);
+
+                    DelayExecution();
+                    goto LockHandle;
+                }
+            }
+            else
+            {
+                DPRINT1("Attempted to convert object 0x%x that is deleted! 
Should never get here!!!\n", hObj);
+                DPRINT1("OldType = 0x%x, Entry->Type = 0x%x, NewType = 0x%x, 
Entry->KernelData = 0x%x\n", OldType, Entry->Type, NewType, Entry->KernelData);
+            }
+        }
+        else if (PrevProcId == LockedProcessId)
+        {
+            GDIDBG_TRACELOOP(hObj, PrevProcId, ProcessId);
+
+            /* the object is currently locked, wait some time and try again.
+               FIXME - we shouldn't loop forever! Give up after some time! */
+            DelayExecution();
+            /* try again */
+            goto LockHandle;
+        }
+        else
+        {
+            DPRINT1("Attempted to convert invalid handle: 0x%x\n", hObj);
+        }
+    }
+
+    return FALSE;
+}
+
+BOOL APIENTRY
 GDIOBJ_SetOwnership(HGDIOBJ ObjectHandle, PEPROCESS NewOwner)
 {
     PGDI_TABLE_ENTRY Entry;

Modified: branches/arwinss/reactos/subsystems/win32/win32k/include/gre.h
URL: 
http://svn.reactos.org/svn/reactos/branches/arwinss/reactos/subsystems/win32/win32k/include/gre.h?rev=42348&r1=42347&r2=42348&view=diff
==============================================================================
--- branches/arwinss/reactos/subsystems/win32/win32k/include/gre.h [iso-8859-1] 
(original)
+++ branches/arwinss/reactos/subsystems/win32/win32k/include/gre.h [iso-8859-1] 
Sun Aug  2 22:53:12 2009
@@ -62,6 +62,10 @@
 INT FASTCALL
 BitsPerFormat(ULONG Format);
 
+/* bitmap.c */
+extern HGDIOBJ hStockBmp;
+VOID CreateStockBitmap();
+
 /* font.c */
 VOID NTAPI
 GreTextOut(PDC pDC, INT x, INT y, UINT flags,

Modified: branches/arwinss/reactos/subsystems/win32/win32k/main/init.c
URL: 
http://svn.reactos.org/svn/reactos/branches/arwinss/reactos/subsystems/win32/win32k/main/init.c?rev=42348&r1=42347&r2=42348&view=diff
==============================================================================
--- branches/arwinss/reactos/subsystems/win32/win32k/main/init.c [iso-8859-1] 
(original)
+++ branches/arwinss/reactos/subsystems/win32/win32k/main/init.c [iso-8859-1] 
Sun Aug  2 22:53:12 2009
@@ -345,6 +345,9 @@
     /* Initialize handle-mapping */
     GDI_InitHandleMapping();
 
+    /* Create stock objects */
+    CreateStockBitmap();
+
     /* Init video driver implementation */
     InitDcImpl();
 

Modified: branches/arwinss/reactos/subsystems/win32/win32k/w32ksvc.db
URL: 
http://svn.reactos.org/svn/reactos/branches/arwinss/reactos/subsystems/win32/win32k/w32ksvc.db?rev=42348&r1=42347&r2=42348&view=diff
==============================================================================
--- branches/arwinss/reactos/subsystems/win32/win32k/w32ksvc.db [iso-8859-1] 
(original)
+++ branches/arwinss/reactos/subsystems/win32/win32k/w32ksvc.db [iso-8859-1] 
Sun Aug  2 22:53:12 2009
@@ -17,7 +17,7 @@
 RosGdiDeleteDC                     1
 RosGdiGetDCOrgEx                   2
 RosGdiPaintRgn                     2
-RosGdiSelectBitmap                 2
+RosGdiSelectBitmap                 3
 RosGdiSelectBrush                  2
 RosGdiSelectFont                   3
 RosGdiSelectPen                    3


Reply via email to