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/winen…
==============================================================================
--- 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/nt…
==============================================================================
--- 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/win3…
==============================================================================
--- 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/win3…
==============================================================================
--- 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/win3…
==============================================================================
--- 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/win3…
==============================================================================
--- 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/win3…
==============================================================================
--- 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/win3…
==============================================================================
--- 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