implemented reuse counters for gdi objects
Modified: trunk/reactos/include/win32k/gdiobj.h
Modified: trunk/reactos/subsys/win32k/objects/gdiobj.c
Modified: trunk/reactos/subsys/win32k/objects/region.c

Modified: trunk/reactos/include/win32k/gdiobj.h
--- trunk/reactos/include/win32k/gdiobj.h	2005-02-18 09:17:56 UTC (rev 13627)
+++ trunk/reactos/include/win32k/gdiobj.h	2005-02-18 12:54:17 UTC (rev 13628)
@@ -19,13 +19,16 @@
 #define GDI_HANDLE_INDEX_MASK (GDI_HANDLE_COUNT - 1)
 #define GDI_HANDLE_TYPE_MASK  0x007f0000
 #define GDI_HANDLE_STOCK_MASK 0x00800000
+#define GDI_HANDLE_REUSE_MASK 0xff000000
 
+#define GDI_HANDLE_REUSECNT_SHIFT 24
+
 #define GDI_HANDLE_CREATE(i, t)    ((HANDLE)(((i) & GDI_HANDLE_INDEX_MASK) | ((t) & GDI_HANDLE_TYPE_MASK)))
-#define GDI_HANDLE_GET_INDEX(h)    (((DWORD)(h)) & GDI_HANDLE_INDEX_MASK)
-#define GDI_HANDLE_GET_TYPE(h)     (((DWORD)(h)) & GDI_HANDLE_TYPE_MASK)
-#define GDI_HANDLE_IS_TYPE(h, t)   ((t) == (((DWORD)(h)) & GDI_HANDLE_TYPE_MASK))
-#define GDI_HANDLE_IS_STOCKOBJ(h)  (0 != (((DWORD)(h)) & GDI_HANDLE_STOCK_MASK))
-#define GDI_HANDLE_SET_STOCKOBJ(h) ((h) = (HANDLE)(((DWORD)(h)) | GDI_HANDLE_STOCK_MASK))
+#define GDI_HANDLE_GET_INDEX(h)    (((ULONG_PTR)(h)) & GDI_HANDLE_INDEX_MASK)
+#define GDI_HANDLE_GET_TYPE(h)     (((ULONG_PTR)(h)) & GDI_HANDLE_TYPE_MASK)
+#define GDI_HANDLE_IS_TYPE(h, t)   ((t) == (((ULONG_PTR)(h)) & GDI_HANDLE_TYPE_MASK))
+#define GDI_HANDLE_IS_STOCKOBJ(h)  (0 != (((ULONG_PTR)(h)) & GDI_HANDLE_STOCK_MASK))
+#define GDI_HANDLE_SET_STOCKOBJ(h) ((h) = (HANDLE)(((ULONG_PTR)(h)) | GDI_HANDLE_STOCK_MASK))
 
 
 /*! \defgroup GDI object types
@@ -74,20 +77,10 @@
 #endif
 } GDIOBJHDR, *PGDIOBJHDR;
 
-typedef struct _GDIMULTILOCK
-{
-  HGDIOBJ hObj;
-  PGDIOBJ pObj;
-  DWORD	ObjectType;
-} GDIMULTILOCK, *PGDIMULTILOCK;
-
-BOOL    INTERNAL_CALL GDIOBJ_LockMultipleObj(PGDIMULTILOCK pList, INT nObj);
-BOOL    INTERNAL_CALL GDIOBJ_UnlockMultipleObj(PGDIMULTILOCK pList, INT nObj);
 BOOL    INTERNAL_CALL GDIOBJ_OwnedByCurrentProcess(HGDIOBJ ObjectHandle);
 void    INTERNAL_CALL GDIOBJ_SetOwnership(HGDIOBJ ObjectHandle, PEPROCESS Owner);
 void    INTERNAL_CALL GDIOBJ_CopyOwnership(HGDIOBJ CopyFrom, HGDIOBJ CopyTo);
 BOOL    INTERNAL_CALL GDIOBJ_ConvertToStockObj(HGDIOBJ *hObj);
-BOOL    INTERNAL_CALL GDIOBJ_LockMultipleObj(PGDIMULTILOCK pList, INT nObj);
 
 #define GDIOBJ_GetObjectType(Handle) \
   GDI_HANDLE_GET_TYPE(Handle)

Modified: trunk/reactos/subsys/win32k/objects/gdiobj.c
--- trunk/reactos/subsys/win32k/objects/gdiobj.c	2005-02-18 09:17:56 UTC (rev 13627)
+++ trunk/reactos/subsys/win32k/objects/gdiobj.c	2005-02-18 12:54:17 UTC (rev 13628)
@@ -377,28 +377,31 @@
 
       RtlZeroMemory(ObjectBody, GetObjectSize(ObjectType));
 
-      TypeInfo = (ObjectType & 0xFFFF0000) | (ObjectType >> 16);
+      TypeInfo = (ObjectType & GDI_HANDLE_TYPE_MASK) | (ObjectType >> 16);
 
       FreeEntry = InterlockedPopEntrySList(&HandleTable->FreeEntriesHead);
       if(FreeEntry != NULL)
       {
         HANDLE PrevProcId;
         UINT Index;
-        HGDIOBJ Handle;
 
         /* calculate the entry from the address of the entry in the free slot array */
         Index = ((ULONG_PTR)FreeEntry - (ULONG_PTR)&HandleTable->FreeEntries[0]) /
                 sizeof(HandleTable->FreeEntries[0]);
         Entry = &HandleTable->Entries[Index];
-        Handle = (HGDIOBJ)((Index & 0xFFFF) | (ObjectType & 0xFFFF0000));
 
 LockHandle:
         PrevProcId = InterlockedCompareExchangePointer(&Entry->ProcessId, LockedProcessId, 0);
         if(PrevProcId == NULL)
         {
+          HGDIOBJ Handle;
+          
           ASSERT(Entry->KernelData == NULL);
 
           Entry->KernelData = ObjectBody;
+          
+          /* copy the reuse-counter */
+          TypeInfo |= Entry->Type & GDI_HANDLE_REUSE_MASK;
 
           /* we found a free entry, no need to exchange this field atomically
              since we're holding the lock */
@@ -416,6 +419,7 @@
           {
             InterlockedIncrement(&W32Process->GDIObjects);
           }
+          Handle = (HGDIOBJ)((Index & 0xFFFF) | (TypeInfo & (GDI_HANDLE_TYPE_MASK | GDI_HANDLE_REUSE_MASK)));
 
           DPRINT("GDIOBJ_AllocObj: 0x%x ob: 0x%x\n", Handle, ObjectBody);
           return Handle;
@@ -425,7 +429,7 @@
 #ifdef GDI_DEBUG
           if(++Attempts > 20)
           {
-            DPRINT1("[%d]Waiting on 0x%x\n", Attempts, Handle);
+            DPRINT1("[%d]Waiting on handle in index 0x%x\n", Attempts, Index);
           }
 #endif
           /* damn, someone is trying to lock the object even though it doesn't
@@ -508,7 +512,8 @@
   PrevProcId = InterlockedCompareExchangePointer(&Entry->ProcessId, LockedProcessId, ProcessId);
   if(PrevProcId == ProcessId)
   {
-    if(Entry->Type != 0 && Entry->KernelData != NULL && (ExpectedType == 0 || ((Entry->Type << 16) == ExpectedType)))
+    if(Entry->Type != 0 && Entry->KernelData != NULL &&
+       (ExpectedType == 0 || ((Entry->Type << 16) == ExpectedType)))
     {
       PGDIOBJHDR GdiHdr;
 
@@ -520,8 +525,8 @@
         PW32PROCESS W32Process = PsGetWin32Process();
         ULONG Type = Entry->Type << 16;
 
-        /* Clear the type field so when unlocking the handle it gets finally deleted */
-        Entry->Type = 0;
+        /* Clear the type field so when unlocking the handle it gets finally deleted and increment reuse counter */
+        Entry->Type = ((Entry->Type >> GDI_HANDLE_REUSECNT_SHIFT) + 1) << GDI_HANDLE_REUSECNT_SHIFT;
         Entry->KernelData = NULL;
 
         /* unlock the handle slot */
@@ -551,8 +556,9 @@
       else
       {
         /* the object is currently locked. just clear the type field so when the
-           object gets unlocked it will be finally deleted from the table. */
-        Entry->Type = 0;
+           object gets unlocked it will be finally deleted from the table. Also
+           incrment the reuse counter! */
+        Entry->Type = ((Entry->Type >> GDI_HANDLE_REUSECNT_SHIFT) + 1) << GDI_HANDLE_REUSECNT_SHIFT;
 
         /* unlock the handle slot */
         InterlockedExchangePointer(&Entry->ProcessId, NULL);
@@ -563,7 +569,7 @@
     }
     else
     {
-      if(Entry->Type != 0)
+      if((Entry->Type & ~GDI_HANDLE_REUSE_MASK) != 0)
       {
         DPRINT1("Attempted to delete object 0x%x, type mismatch (0x%x : 0x%x)\n", hObj, ObjectType, ExpectedType);
       }
@@ -610,85 +616,6 @@
 }
 
 /*!
- * Lock multiple objects. Use this function when you need to lock multiple objects and some of them may be
- * duplicates. You should use this function to avoid trying to lock the same object twice!
- *
- * \param	pList 	pointer to the list that contains handles to the objects. You should set hObj and ObjectType fields.
- * \param	nObj	number of objects to lock
- * \return	for each entry in pList this function sets pObj field to point to the object.
- *
- * \note this function uses an O(n^2) algoritm because we shouldn't need to call it with more than 3 or 4 objects.
-*/
-BOOL INTERNAL_CALL
-GDIOBJ_LockMultipleObj(PGDIMULTILOCK pList, INT nObj)
-{
-  INT i, j;
-  ASSERT( pList );
-  /* FIXME - check for "invalid" handles */
-  /* go through the list checking for duplicate objects */
-  for (i = 0; i < nObj; i++)
-    {
-      pList[i].pObj = NULL;
-      for (j = 0; j < i; j++)
-	{
-	  if (pList[i].hObj == pList[j].hObj)
-	    {
-	      /* already locked, so just copy the pointer to the object */
-	      pList[i].pObj = pList[j].pObj;
-	      break;
-	    }
-	}
-
-      if (NULL == pList[i].pObj)
-	{
-	  /* object hasn't been locked, so lock it. */
-	  if (NULL != pList[i].hObj)
-	    {
-	      pList[i].pObj = GDIOBJ_LockObj(pList[i].hObj, pList[i].ObjectType);
-	    }
-	}
-    }
-
-  return TRUE;
-}
-
-/*!
- * Unlock multiple objects. Use this function when you need to unlock multiple objects and some of them may be
- * duplicates.
- *
- * \param	pList 	pointer to the list that contains handles to the objects. You should set hObj and ObjectType fields.
- * \param	nObj	number of objects to lock
- *
- * \note this function uses O(n^2) algoritm because we shouldn't need to call it with more than 3 or 4 objects.
-*/
-BOOL INTERNAL_CALL
-GDIOBJ_UnlockMultipleObj(PGDIMULTILOCK pList, INT nObj)
-{
-  INT i, j;
-  ASSERT(pList);
-
-  /* go through the list checking for duplicate objects */
-  for (i = 0; i < nObj; i++)
-    {
-      if (NULL != pList[i].pObj)
-	{
-	  for (j = i + 1; j < nObj; j++)
-	    {
-	      if ((pList[i].pObj == pList[j].pObj))
-		{
-		  /* set the pointer to zero for all duplicates */
-		  pList[j].pObj = NULL;
-		}
-	    }
-	  GDIOBJ_UnlockObj(pList[i].hObj);
-	  pList[i].pObj = NULL;
-	}
-    }
-
-  return TRUE;
-}
-
-/*!
  * Initialization of the GDI object engine.
 */
 VOID INTERNAL_CALL
@@ -744,11 +671,11 @@
 
     End = &HandleTable->Entries[GDI_HANDLE_COUNT];
     for(Entry = &HandleTable->Entries[RESERVE_ENTRIES_COUNT];
-        Entry < End;
+        Entry != End;
         Entry++, Index++)
     {
       /* ignore the lock bit */
-      if((HANDLE)((ULONG_PTR)Entry->ProcessId & ~0x1) == ProcId && Entry->Type != 0)
+      if((HANDLE)((ULONG_PTR)Entry->ProcessId & ~0x1) == ProcId && (Entry->Type & ~GDI_HANDLE_REUSE_MASK) != 0)
       {
         HGDIOBJ ObjectHandle;
 
@@ -824,7 +751,8 @@
     /* we're locking an object that belongs to our process or it's a global
        object if ProcessId == 0 here. ProcessId can only be 0 here if it previously
        failed to lock the object and it turned out to be a global object. */
-    if(EntryType != 0 && Entry->KernelData != NULL && (ExpectedType == 0 || (EntryType == ExpectedType)))
+    if(EntryType != 0 && Entry->KernelData != NULL &&
+       (ExpectedType == 0 || (EntryType == ExpectedType)))
     {
       PETHREAD PrevThread;
       PGDIOBJHDR GdiHdr;
@@ -870,14 +798,15 @@
     {
       InterlockedExchangePointer(&Entry->ProcessId, PrevProcId);
 
-      if(EntryType == 0)
+      if((EntryType & ~GDI_HANDLE_REUSE_MASK) == 0)
       {
         DPRINT1("Attempted to lock object 0x%x that is deleted!\n", hObj);
         KeRosDumpStackFrames ( NULL, 20 );
       }
       else
       {
-        DPRINT1("Attempted to lock object 0x%x, type mismatch (0x%x : 0x%x)\n", hObj, EntryType, ExpectedType);
+        DPRINT1("Attempted to lock object 0x%x, type mismatch (0x%x : 0x%x)\n",
+                hObj, EntryType & ~GDI_HANDLE_REUSE_MASK, ExpectedType & ~GDI_HANDLE_REUSE_MASK);
         KeRosDumpStackFrames ( NULL, 20 );
       }
 #ifdef GDI_DEBUG
@@ -981,7 +910,7 @@
 #endif
         }
 
-        if(Entry->Type == 0 && GdiHdr->Locks == 0)
+        if((Entry->Type & ~GDI_HANDLE_REUSE_MASK) == 0 && GdiHdr->Locks == 0)
         {
           PPAGED_LOOKASIDE_LIST LookasideList;
           PW32PROCESS W32Process = PsGetWin32Process();
@@ -1095,7 +1024,7 @@
 
     Entry = GDI_HANDLE_GET_ENTRY(HandleTable, ObjectHandle);
     Ret = Entry->KernelData != NULL &&
-          Entry->Type != 0 &&
+          (Entry->Type & ~GDI_HANDLE_REUSE_MASK) != 0 &&
           (HANDLE)((ULONG_PTR)Entry->ProcessId & ~0x1) == ProcessId;
 
     return Ret;
@@ -1143,6 +1072,8 @@
          exchange it.*/
       NewType = GDI_HANDLE_GET_TYPE(*hObj);
       NewType |= NewType >> 16;
+      NewType |= (ULONG_PTR)(*hObj) & GDI_HANDLE_REUSE_MASK;
+      
       /* This is the type that the object should have right now, save it */
       OldType = NewType;
       /* As the object should be a stock object, set it's flag, but only in the upper 16 bits */
@@ -1268,7 +1199,7 @@
     {
       PETHREAD PrevThread;
 
-      if(Entry->Type != 0 && Entry->KernelData != NULL)
+      if((Entry->Type & ~GDI_HANDLE_REUSE_MASK) != 0 && Entry->KernelData != NULL)
       {
         PGDIOBJHDR GdiHdr = GDIBdyToHdr(Entry->KernelData);
 
@@ -1401,7 +1332,7 @@
       PETHREAD PrevThread;
       PGDIOBJHDR GdiHdr;
 
-      if(FromEntry->Type != 0 && FromEntry->KernelData != NULL)
+      if((FromEntry->Type & ~GDI_HANDLE_REUSE_MASK) != 0 && FromEntry->KernelData != NULL)
       {
         GdiHdr = GDIBdyToHdr(FromEntry->KernelData);
 

Modified: trunk/reactos/subsys/win32k/objects/region.c
--- trunk/reactos/subsys/win32k/objects/region.c	2005-02-18 09:17:56 UTC (rev 13627)
+++ trunk/reactos/subsys/win32k/objects/region.c	2005-02-18 12:54:17 UTC (rev 13628)
@@ -707,45 +707,43 @@
 HRGN FASTCALL REGION_CropRgn(HRGN hDst, HRGN hSrc, const PRECT lpRect, PPOINT lpPt)
 {
   PROSRGNDATA objSrc, rgnDst;
-  HRGN hNewDst, hRet = NULL;
-  GDIMULTILOCK Lock[2] = {{hDst, 0, GDI_OBJECT_TYPE_REGION}, {hSrc, 0, GDI_OBJECT_TYPE_REGION}};
+  HRGN hRet = NULL;
+  POINT pt = { 0, 0 };
 
   if( !hDst )
     {
-      if( !( hNewDst = RGNDATA_AllocRgn(1) ) )
+      if( !( hDst = RGNDATA_AllocRgn(1) ) )
 	{
 	  return 0;
 	}
-      Lock[0].hObj = hNewDst;
     }
 
-  if ( !GDIOBJ_LockMultipleObj(Lock, sizeof(Lock)/sizeof(Lock[0])) )
-    {
-      DPRINT1("GDIOBJ_LockMultipleObj() failed\n" );
-      return 0;
-    }
-  rgnDst = Lock[0].pObj;
-  objSrc = Lock[1].pObj;
-
-  if( objSrc && rgnDst )
+  rgnDst = RGNDATA_LockRgn(hDst);
+  if(rgnDst == NULL)
   {
-    if(rgnDst)
-    {
-      POINT pt = { 0, 0 };
+    return NULL;
+  }
+  
+  objSrc = RGNDATA_LockRgn(hSrc);
+  if(objSrc == NULL)
+  {
+    RGNDATA_UnlockRgn(hDst);
+    return NULL;
+  }
+  if(!lpPt)
+  	lpPt = &pt;
 
-	  if(!lpPt)
-	  	lpPt = &pt;
-
-      if(REGION_CropAndOffsetRegion(lpPt, lpRect, objSrc, rgnDst) == FALSE)
-	  { // ve failed cleanup and return
-		hRet = NULL;
-      }
-      else{ // ve are fine. unlock the correct pointer and return correct handle
-		hRet = Lock[0].hObj;
-	  }
+    if(REGION_CropAndOffsetRegion(lpPt, lpRect, objSrc, rgnDst) == FALSE)
+  { // ve failed cleanup and return
+	hRet = NULL;
     }
+    else{ // ve are fine. unlock the correct pointer and return correct handle
+	hRet = hDst;
   }
-  GDIOBJ_UnlockMultipleObj(Lock, sizeof(Lock)/sizeof(Lock[0]));
+
+  RGNDATA_UnlockRgn(hSrc);
+  RGNDATA_UnlockRgn(hDst);
+  
   return hRet;
 }
 
@@ -1957,21 +1955,12 @@
                     INT  CombineMode)
 {
   INT result = ERROR;
-  GDIMULTILOCK Lock[3] = {{hDest, 0, GDI_OBJECT_TYPE_REGION}, {hSrc1, 0, GDI_OBJECT_TYPE_REGION}, {hSrc2, 0, GDI_OBJECT_TYPE_REGION}};
   PROSRGNDATA destRgn, src1Rgn, src2Rgn;
-
-  if ( !GDIOBJ_LockMultipleObj(Lock, sizeof(Lock)/sizeof(Lock[0])) )
-    {
-      DPRINT1("GDIOBJ_LockMultipleObj() failed\n" );
-      return ERROR;
-    }
-
-  destRgn = (PROSRGNDATA) Lock[0].pObj;
-  src1Rgn = (PROSRGNDATA) Lock[1].pObj;
-  src2Rgn = (PROSRGNDATA) Lock[2].pObj;
-
+  
+  destRgn = RGNDATA_LockRgn(hDest);
   if( destRgn )
     {
+      src1Rgn = RGNDATA_LockRgn(hSrc1);
       if( src1Rgn )
 	  {
 	    if (CombineMode == RGN_COPY)
@@ -1982,7 +1971,8 @@
 	      }
 	    else
 	    {
-	      if( src2Rgn )
+              src2Rgn = RGNDATA_LockRgn(hSrc2);
+              if( src2Rgn )
 		{
 		  switch (CombineMode)
 		    {
@@ -1999,17 +1989,26 @@
 			REGION_SubtractRegion(destRgn, src1Rgn, src2Rgn);
 			break;
 		    }
+		  RGNDATA_UnlockRgn(hSrc2);
 		  result = destRgn->rdh.iType;
 		}
+		else
+                {
+                  DPRINT1("NtGdiCombineRgn requires hSrc2 != NULL for combine mode %d!\n", CombineMode);
+                }
 	    }
+
+            RGNDATA_UnlockRgn(hSrc1);
 	  }
+
+      RGNDATA_UnlockRgn(hDest);
     }
   else
     {
       DPRINT("NtGdiCombineRgn: hDest unavailable\n");
       result = ERROR;
     }
-  GDIOBJ_UnlockMultipleObj(Lock, sizeof(Lock)/sizeof(Lock[0]));
+
   return result;
 }