simplification of irql manipulation in a couple of places - patch by Mike Nordell
[reactos.git] / reactos / subsys / win32k / objects / gdiobj.c
index 709027b..c7b4ef4 100644 (file)
@@ -19,7 +19,7 @@
 /*
  * GDIOBJ.C - GDI object manipulation routines
  *
- * $Id: gdiobj.c,v 1.36 2003/08/18 10:18:14 hbirr Exp $
+ * $Id: gdiobj.c,v 1.47 2003/10/16 03:26:51 vizzini Exp $
  *
  */
 
 #define NDEBUG
 #include <win32k/debug1.h>
 
-#define GDI_HANDLE2INDEX(h) (((WORD)(size_t)(h)) & 0xffff)
-#define GDI_INDEX2HANDLE(i) ((HANDLE)  (((size_t)(i))&0xffff)  )
+/*! Size of the GDI handle table
+ * http://www.windevnet.com/documents/s=7290/wdj9902b/9902b.htm
+ * gdi handle table can hold 0x4000 handles
+*/
+#define GDI_HANDLE_COUNT 0x4000
+
+#define GDI_GLOBAL_PROCESS ((HANDLE) 0xffffffff)
 
-//  GDI stock objects
+#define GDI_HANDLE_INDEX_MASK (GDI_HANDLE_COUNT - 1)
+#define GDI_HANDLE_TYPE_MASK  0x007f0000
+#define GDI_HANDLE_STOCK_MASK 0x00800000
+
+#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_TYPE_TO_MAGIC(t) ((WORD) ((t) >> 16))
+#define GDI_MAGIC_TO_TYPE(m) ((DWORD)(m) << 16)
+
+#define GDI_VALID_OBJECT(h, obj, t, f) \
+  (NULL != (obj) \
+   && (GDI_MAGIC_TO_TYPE((obj)->Magic) == (t) || GDI_OBJECT_TYPE_DONTCARE == (t)) \
+   && (GDI_HANDLE_GET_TYPE((h)) == GDI_MAGIC_TO_TYPE((obj)->Magic)) \
+   && (((obj)->hProcessId == PsGetCurrentProcessId()) \
+       || (GDI_GLOBAL_PROCESS == (obj)->hProcessId) \
+       || ((f) & GDIOBJFLAG_IGNOREPID)))
+
+typedef struct _GDI_HANDLE_TABLE
+{
+  WORD  wTableSize;
+  PGDIOBJHDR Handles[1];
+} GDI_HANDLE_TABLE, *PGDI_HANDLE_TABLE;
+
+/*  GDI stock objects */
 
 static LOGBRUSH WhiteBrush =
 { BS_SOLID, RGB(255,255,255), 0 };
@@ -81,97 +114,78 @@ static LOGFONTW OEMFixedFont =
 { 14, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, OEM_CHARSET,
   0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, L"" };
 
-/* Filler to make the location counter dword aligned again.  This is necessary
-   since (a) LOGFONT is packed, (b) gcc places initialised variables in the code
-   segment, and (c) Solaris assembler is stupid.  */
-//static UINT align_OEMFixedFont = 1;
-
 static LOGFONTW AnsiFixedFont =
 { 14, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
   0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, L"" };
 
-//static UINT align_AnsiFixedFont = 1;
-
-//static LOGFONTW AnsiVarFont =
-//{ 14, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
-//  0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, L"MS Sans Serif" };
-
-//static UINT align_AnsiVarFont = 1;
+/*static LOGFONTW AnsiVarFont =
+ *{ 14, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
+ *  0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, L"MS Sans Serif" }; */
 
 static LOGFONTW SystemFont =
 { 14, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
   0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, L"System" };
 
-//static UINT align_SystemFont = 1;
-
 static LOGFONTW DeviceDefaultFont =
 { 14, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
   0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, L"" };
 
-//static UINT align_DeviceDefaultFont = 1;
-
 static LOGFONTW SystemFixedFont =
 { 14, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
   0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, L"" };
 
-//static UINT align_SystemFixedFont = 1;
-
 /* FIXME: Is this correct? */
 static LOGFONTW DefaultGuiFont =
 { 14, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
   0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, L"MS Sans Serif" };
 
-//static UINT align_DefaultGuiFont = 1;
-
-static HGDIOBJ *StockObjects[NB_STOCK_OBJECTS]; // we dont assign these statically as WINE does because we might redesign
-                                                // the way handles work, so it's more dynamic now
-
-
-HBITMAP hPseudoStockBitmap; /*! 1x1 bitmap for memory DCs */
+#define NB_STOCK_OBJECTS (DEFAULT_GUI_FONT + 1)
 
+static HGDIOBJ *StockObjects[NB_STOCK_OBJECTS];
 static PGDI_HANDLE_TABLE  HandleTable = 0;
 static FAST_MUTEX  HandleTableMutex;
 static FAST_MUTEX  RefCountHandling;
 
-/*! Size of the GDI handle table
- * per http://www.wd-mag.com/articles/1999/9902/9902b/9902b.htm?topic=articles
- * gdi handle table can hold 0x4000 handles
-*/
-#define GDI_HANDLE_NUMBER  0x4000
-
 /*!
  * Allocate GDI object table.
  * \param      Size - number of entries in the object table.
+ * Notes:: Must be called at IRQL < DISPATCH_LEVEL.
 */
 static PGDI_HANDLE_TABLE FASTCALL
 GDIOBJ_iAllocHandleTable (WORD Size)
 {
   PGDI_HANDLE_TABLE  handleTable;
 
+  /* prevent APC delivery for the *FastMutexUnsafe calls */
+  const KIRQL PrevIrql = KfRaiseIrql(APC_LEVEL);
   ExAcquireFastMutexUnsafe (&HandleTableMutex);
   handleTable = ExAllocatePool(PagedPool,
-                               sizeof (GDI_HANDLE_TABLE) +
-                                 sizeof (GDI_HANDLE_ENTRY) * Size);
+                               sizeof(GDI_HANDLE_TABLE) +
+                               sizeof(PGDIOBJ) * Size);
   ASSERT( handleTable );
   memset (handleTable,
           0,
-          sizeof (GDI_HANDLE_TABLE) + sizeof (GDI_HANDLE_ENTRY) * Size);
+          sizeof(GDI_HANDLE_TABLE) + sizeof(PGDIOBJ) * Size);
   handleTable->wTableSize = Size;
   ExReleaseFastMutexUnsafe (&HandleTableMutex);
+  KfLowerIrql(PrevIrql);
 
-  return  handleTable;
+  return handleTable;
 }
 
 /*!
  * Returns the entry into the handle table by index.
 */
-static PGDI_HANDLE_ENTRY FASTCALL
-GDIOBJ_iGetHandleEntryForIndex (WORD TableIndex)
+static PGDIOBJHDR FASTCALL
+GDIOBJ_iGetObjectForIndex(WORD TableIndex)
 {
-  //DPRINT("GDIOBJ_iGetHandleEntryForIndex: TableIndex: %d,\n handle: %x, ptr: %x\n", TableIndex, HandleTable->Handles [TableIndex], &(HandleTable->Handles [TableIndex])  );
-  //DPRINT("GIG: HandleTable: %x, Handles: %x, \n TableIndex: %x, pt: %x\n", HandleTable,  HandleTable->Handles, TableIndex, ((PGDI_HANDLE_ENTRY)HandleTable->Handles+TableIndex));
-  //DPRINT("GIG: Hndl: %x, mag: %x\n", ((PGDI_HANDLE_ENTRY)HandleTable->Handles+TableIndex), ((PGDI_HANDLE_ENTRY)HandleTable->Handles+TableIndex)->wMagic);
-  return  ((PGDI_HANDLE_ENTRY)HandleTable->Handles+TableIndex);
+  if (0 == TableIndex || HandleTable->wTableSize < TableIndex)
+    {
+      DPRINT1("Invalid TableIndex %u\n", (unsigned) TableIndex);
+      return NULL;
+    }
+
+  return HandleTable->Handles[TableIndex];
 }
 
 /*!
@@ -181,20 +195,23 @@ GDIOBJ_iGetHandleEntryForIndex (WORD TableIndex)
 static WORD FASTCALL
 GDIOBJ_iGetNextOpenHandleIndex (void)
 {
-  WORD  tableIndex;
+  WORD tableIndex;
 
+  /* prevent APC delivery for the *FastMutexUnsafe calls */
+  const KIRQL PrevIrql = KfRaiseIrql(APC_LEVEL);
   ExAcquireFastMutexUnsafe (&HandleTableMutex);
   for (tableIndex = 1; tableIndex < HandleTable->wTableSize; tableIndex++)
-  {
-    if (HandleTable->Handles [tableIndex].wMagic == 0)
     {
-      HandleTable->Handles [tableIndex].wMagic = GO_MAGIC_DONTCARE;
-      break;
+      if (NULL == HandleTable->Handles[tableIndex])
+       {
+         HandleTable->Handles[tableIndex] = (PGDIOBJHDR) -1;
+         break;
+       }
     }
-  }
   ExReleaseFastMutexUnsafe (&HandleTableMutex);
+  KfLowerIrql(PrevIrql);
 
-  return  (tableIndex < HandleTable->wTableSize) ? tableIndex : 0;
+  return (tableIndex < HandleTable->wTableSize) ? tableIndex : 0;
 }
 
 /*!
@@ -202,46 +219,56 @@ GDIOBJ_iGetNextOpenHandleIndex (void)
  *
  * \param Size - size of the GDI object. This shouldn't to include the size of GDIOBJHDR.
  * The actual amount of allocated memory is sizeof(GDIOBJHDR)+Size
- * \param Magic - object magic (see GDI Magic)
+ * \param ObjectType - type of object \ref GDI object types
+ * \param CleanupProcPtr - Routine to be called on destruction of object
  *
  * \return Handle of the allocated object.
  *
  * \note Use GDIOBJ_Lock() to obtain pointer to the new object.
 */
 HGDIOBJ FASTCALL
-GDIOBJ_AllocObj(WORD Size, WORD Magic)
+GDIOBJ_AllocObj(WORD Size, DWORD ObjectType, GDICLEANUPPROC CleanupProc)
 {
   PGDIOBJHDR  newObject;
-  PGDI_HANDLE_ENTRY  handleEntry;
+  WORD Index;
+  
+  Index = GDIOBJ_iGetNextOpenHandleIndex ();
+  if (0 == Index)
+    {
+      DPRINT1("Out of GDI handles\n");
+      return NULL;
+    }
 
-  DPRINT("GDIOBJ_AllocObj: size: %d, magic: %x\n", Size, Magic);
-  newObject = ExAllocatePool (PagedPool, Size + sizeof (GDIOBJHDR));
+  DPRINT("GDIOBJ_AllocObj: handle: %d, size: %d, type: 0x%08x\n", Index, Size, ObjectType);
+  newObject = ExAllocatePool(PagedPool, Size + sizeof (GDIOBJHDR));
   if (newObject == NULL)
   {
-    DPRINT("GDIOBJ_AllocObj: failed\n");
-    return  NULL;
+    DPRINT1("GDIOBJ_AllocObj: failed\n");
+    return NULL;
   }
-  RtlZeroMemory (newObject, Size + sizeof (GDIOBJHDR));
+  RtlZeroMemory (newObject, Size + sizeof(GDIOBJHDR));
+
+  newObject->wTableIndex = Index;
 
-  newObject->wTableIndex = GDIOBJ_iGetNextOpenHandleIndex ();
   newObject->dwCount = 0;
-  handleEntry = GDIOBJ_iGetHandleEntryForIndex (newObject->wTableIndex);
-  handleEntry->wMagic = Magic;
-  handleEntry->hProcessId = PsGetCurrentProcessId ();
-  handleEntry->pObject = newObject;
-  handleEntry->lockfile = NULL;
-  handleEntry->lockline = 0;
-  DPRINT("GDIOBJ_AllocObj: object handle %d\n", newObject->wTableIndex );
-  return GDI_INDEX2HANDLE(newObject->wTableIndex);
+  newObject->hProcessId = PsGetCurrentProcessId ();
+  newObject->CleanupProc = CleanupProc;
+  newObject->Magic = GDI_TYPE_TO_MAGIC(ObjectType);
+  newObject->lockfile = NULL;
+  newObject->lockline = 0;
+  HandleTable->Handles[Index] = newObject;
+
+  return GDI_HANDLE_CREATE(Index, ObjectType);
 }
 
 /*!
  * Free memory allocated for the GDI object. For each object type this function calls the
  * appropriate cleanup routine.
  *
- * \param hObj - handle of the object to be deleted.
- * \param Magic - object magic or GO_MAGIC_DONTCARE.
- * \param Flag - if set to GDIOBJFLAG_IGNOREPID then the routine doesn't check if the process that
+ * \param hObj       - handle of the object to be deleted.
+ * \param ObjectType - one of the \ref GDI object types
+ * or GDI_OBJECT_TYPE_DONTCARE.
+ * \param Flag       - if set to GDIOBJFLAG_IGNOREPID then the routine doesn't check if the process that
  * tries to delete the object is the same one that created it.
  *
  * \return Returns TRUE if succesful.
@@ -250,114 +277,92 @@ GDIOBJ_AllocObj(WORD Size, WORD Magic)
  * \note This function deferres object deletion if it is still in use.
 */
 BOOL STDCALL
-GDIOBJ_FreeObj(HGDIOBJ hObj, WORD Magic, DWORD Flag)
+GDIOBJ_FreeObj(HGDIOBJ hObj, DWORD ObjectType, DWORD Flag)
 {
-       PGDIOBJHDR  objectHeader;
-       PGDI_HANDLE_ENTRY  handleEntry;
-       PGDIOBJ         Obj;
-       BOOL    bRet = TRUE;
+  PGDIOBJHDR objectHeader;
+  PGDIOBJ Obj;
+  BOOL         bRet = TRUE;
 
-       handleEntry = GDIOBJ_iGetHandleEntryForIndex ( GDI_HANDLE2INDEX(hObj) );
-       DPRINT("GDIOBJ_FreeObj: hObj: %d, magic: %x, handleEntry: %x\n", (WORD)hObj & 0xffff, Magic, handleEntry );
+  objectHeader = GDIOBJ_iGetObjectForIndex(GDI_HANDLE_GET_INDEX(hObj));
+  DPRINT("GDIOBJ_FreeObj: hObj: 0x%08x, object: %x\n", hObj, objectHeader);
 
-       if (handleEntry == 0 || (handleEntry->wMagic != Magic && Magic != GO_MAGIC_DONTCARE )
-            || ((handleEntry->hProcessId != PsGetCurrentProcessId()) && !(Flag & GDIOBJFLAG_IGNOREPID))){
+  if (! GDI_VALID_OBJECT(hObj, objectHeader, ObjectType, Flag)
+      || GDI_GLOBAL_PROCESS == objectHeader->hProcessId)
 
-         DPRINT("Can't Delete hObj: %d, magic: %x, pid:%d\n currpid:%d, flag:%d, hmm:%d\n",(WORD)hObj & 0xffff, handleEntry->wMagic, handleEntry->hProcessId, PsGetCurrentProcessId(), (Flag&GDIOBJFLAG_IGNOREPID), ((handleEntry->hProcessId != PsGetCurrentProcessId()) && !(Flag&GDIOBJFLAG_IGNOREPID)) );
-         return  FALSE;
-       }
+    {
+      DPRINT1("Can't delete hObj:0x%08x, type:0x%08x, flag:%d\n", hObj, ObjectType, Flag);
+      return FALSE;
+    }
 
-       objectHeader = handleEntry->pObject;
-       ASSERT(objectHeader);
-       DPRINT("FreeObj: locks: %x\n", objectHeader->dwCount );
-       if( !(Flag & GDIOBJFLAG_IGNORELOCK) ){
-               // check that the reference count is zero. if not then set flag
-               // and delete object when releaseobj is called
-               ExAcquireFastMutex(&RefCountHandling);
-               if( ( objectHeader->dwCount & ~0x80000000 ) > 0 ){
-                       DPRINT("GDIOBJ_FreeObj: delayed object deletion: count %d\n", objectHeader->dwCount);
-                       objectHeader->dwCount |= 0x80000000;
-                       ExReleaseFastMutex(&RefCountHandling);
-                       return TRUE;
-               }
-               ExReleaseFastMutex(&RefCountHandling);
+  DPRINT("FreeObj: locks: %x\n", objectHeader->dwCount );
+  if (!(Flag & GDIOBJFLAG_IGNORELOCK))
+    {
+      /* check that the reference count is zero. if not then set flag
+       * and delete object when releaseobj is called */
+      ExAcquireFastMutex(&RefCountHandling);
+      if ((objectHeader->dwCount & ~0x80000000) > 0 )
+       {
+         DPRINT("GDIOBJ_FreeObj: delayed object deletion: count %d\n", objectHeader->dwCount);
+         objectHeader->dwCount |= 0x80000000;
+         ExReleaseFastMutex(&RefCountHandling);
+         return TRUE;
        }
+      ExReleaseFastMutex(&RefCountHandling);
+    }
 
-       //allow object to delete internal data
-       Obj = (PGDIOBJ)((PCHAR)handleEntry->pObject + sizeof(GDIOBJHDR));
-       switch( handleEntry->wMagic ){
-               case GO_REGION_MAGIC:
-                       bRet = RGNDATA_InternalDelete( (PROSRGNDATA) Obj );
-                       break;
-               case GO_BITMAP_MAGIC:
-                       bRet = Bitmap_InternalDelete( (PBITMAPOBJ) Obj );
-                       break;
-               case GO_DC_MAGIC:
-                       bRet = DC_InternalDeleteDC( (PDC) Obj );
-                       break;
-               case GO_PEN_MAGIC:
-               case GO_PALETTE_MAGIC:
-               case GO_DISABLED_DC_MAGIC:
-               case GO_META_DC_MAGIC:
-               case GO_METAFILE_MAGIC:
-               case GO_METAFILE_DC_MAGIC:
-               case GO_ENHMETAFILE_MAGIC:
-               case GO_ENHMETAFILE_DC_MAGIC:
-
-               case GO_BRUSH_MAGIC:
-               case GO_FONT_MAGIC:
-                       break;
-               case GO_DCE_MAGIC:
-                       bRet = DCE_InternalDelete( (PDCE) Obj );
-                       break;
-               case GO_ICONCURSOR_MAGIC:
-                       bRet = IconCursor_InternalDelete( (PICONCURSOROBJ) Obj );
-                       break;
-       }
-       ExFreePool (handleEntry->pObject);
-       memset ( handleEntry, 0, sizeof(GDI_HANDLE_ENTRY) );
+  /* allow object to delete internal data */
+  if (NULL != objectHeader->CleanupProc)
+    {
+      Obj = (PGDIOBJ)((PCHAR)objectHeader + sizeof(GDIOBJHDR));
+      bRet = (*(objectHeader->CleanupProc))(Obj);
+    }
+
+  ExFreePool(objectHeader);
+  HandleTable->Handles[GDI_HANDLE_GET_INDEX(hObj)] = NULL;
 
-       return  TRUE;
+  return bRet;
 }
 
 /*!
  * 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 Magic fields.
+ * \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 FASTCALL
-GDIOBJ_LockMultipleObj( PGDIMULTILOCK pList, INT nObj )
+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++ )
+  /* 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++ )
+      pList[i].pObj = NULL;
+      for (j = 0; j < i; j++)
        {
-         if( ((pList+i)->hObj == (pList+j)->hObj)
-             && ((pList+i)->Magic == (pList+j)->Magic)
-           )
+         if (pList[i].hObj == pList[j].hObj)
            {
-             //already locked, so just copy the pointer to the object
-             (pList+i)->pObj = (pList+j)->pObj;
+             /* already locked, so just copy the pointer to the object */
+             pList[i].pObj = pList[j].pObj;
              break;
            }
        }
-      if( (pList+i)->pObj == NULL )
-      {
-       //object hasn't been locked, so lock it.
-       if ( (pList+i)->hObj )
-         (pList+i)->pObj = GDIOBJ_LockObj( (pList+i)->hObj, (pList+i)->Magic );
-      }
+
+      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;
 }
 
@@ -365,38 +370,40 @@ GDIOBJ_LockMultipleObj( PGDIMULTILOCK pList, INT nObj )
  * 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 Magic fields.
+ * \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 FASTCALL
-GDIOBJ_UnlockMultipleObj( PGDIMULTILOCK pList, INT nObj )
+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++ )
+  ASSERT(pList);
+
+  /* go through the list checking for duplicate objects */
+  for (i = 0; i < nObj; i++)
     {
-      if( (pList+i)->pObj != NULL )
+      if (NULL != pList[i].pObj)
        {
-         for( j = i+1; j < nObj; j++ )
+         for (j = i + 1; j < nObj; j++)
            {
-             if( ((pList+i)->pObj == (pList+j)->pObj) )
+             if ((pList[i].pObj == pList[j].pObj))
                {
-                 //set the pointer to zero for all duplicates
-                 (pList+j)->pObj = NULL;
+                 /* set the pointer to zero for all duplicates */
+                 pList[j].pObj = NULL;
                }
            }
-         GDIOBJ_UnlockObj( (pList+i)->hObj, (pList+i)->Magic );
-         (pList+i)->pObj = NULL;
+         GDIOBJ_UnlockObj(pList[i].hObj, pList[i].ObjectType);
+         pList[i].pObj = NULL;
        }
     }
+
   return TRUE;
 }
 
 /*!
- * Marks the object as global. (Creator process ID is set to 0xFFFFFFFF). Global objects may be
+ * Marks the object as global. (Creator process ID is set to GDI_GLOBAL_PROCESS). Global objects may be
  * accessed by any process.
  * \param      ObjectHandle - handle of the object to make global.
  *
@@ -405,38 +412,61 @@ GDIOBJ_UnlockMultipleObj( PGDIMULTILOCK pList, INT nObj )
 VOID FASTCALL
 GDIOBJ_MarkObjectGlobal(HGDIOBJ ObjectHandle)
 {
-  PGDI_HANDLE_ENTRY  handleEntry;
+  PGDIOBJHDR ObjHdr;
+
+  DPRINT("GDIOBJ_MarkObjectGlobal handle 0x%08x\n", ObjectHandle);
+  ObjHdr = GDIOBJ_iGetObjectForIndex(GDI_HANDLE_GET_INDEX(ObjectHandle));
+  if (NULL == ObjHdr)
+    {
+      return;
+    }
 
-  if (ObjectHandle == NULL)
-    return;
+  ObjHdr->hProcessId = GDI_GLOBAL_PROCESS;
+}
 
-  handleEntry = GDIOBJ_iGetHandleEntryForIndex ( GDI_HANDLE2INDEX(ObjectHandle) );
-  if (handleEntry == 0)
-    return;
+/*!
+ * Removes the global mark from the object. Global objects may be
+ * accessed by any process.
+ * \param      ObjectHandle - handle of the object to make local.
+ *
+ * \note       Only stock objects should be marked global.
+*/
+VOID FASTCALL
+GDIOBJ_UnmarkObjectGlobal(HGDIOBJ ObjectHandle)
+{
+  PGDIOBJHDR ObjHdr;
 
-  handleEntry->hProcessId = (HANDLE)0xFFFFFFFF;
+  DPRINT("GDIOBJ_MarkObjectGlobal handle 0x%08x\n", ObjectHandle);
+  ObjHdr = GDIOBJ_iGetObjectForIndex(GDI_HANDLE_GET_INDEX(ObjectHandle));
+  if (NULL == ObjHdr || GDI_GLOBAL_PROCESS != ObjHdr->hProcessId)
+    {
+      return;
+    }
+
+  ObjHdr->hProcessId = PsGetCurrentProcessId();
 }
 
 /*!
- * Get the type (magic value) of the object.
+ * Get the type of the object.
  * \param      ObjectHandle - handle of the object.
- * \return     GDI Magic value.
+ * \return     One of the \ref GDI object types
 */
-WORD FASTCALL
-GDIOBJ_GetHandleMagic (HGDIOBJ ObjectHandle)
+DWORD FASTCALL
+GDIOBJ_GetObjectType(HGDIOBJ ObjectHandle)
 {
-  PGDI_HANDLE_ENTRY  handleEntry;
-
-  if (ObjectHandle == NULL)
-    return  0;
+  PGDIOBJHDR ObjHdr;
 
-  handleEntry = GDIOBJ_iGetHandleEntryForIndex ( GDI_HANDLE2INDEX(ObjectHandle) );
-  if (handleEntry == 0 ||
-      (handleEntry->hProcessId != (HANDLE)0xFFFFFFFF &&
-       handleEntry->hProcessId != PsGetCurrentProcessId ()))
-    return  0;
+  ObjHdr = GDIOBJ_iGetObjectForIndex(GDI_HANDLE_GET_INDEX(ObjectHandle));
+  if (NULL == ObjHdr
+      || ! GDI_VALID_OBJECT(ObjectHandle, ObjHdr, GDI_MAGIC_TO_TYPE(ObjHdr->Magic), 0))
+    {
+      DPRINT1("Invalid ObjectHandle 0x%08x\n", ObjectHandle);
+      return 0;
+    }
+  DPRINT("GDIOBJ_GetObjectType for handle 0x%08x returns 0x%08x\n", ObjectHandle,
+         GDI_MAGIC_TO_TYPE(ObjHdr->Magic));
 
-  return  handleEntry->wMagic;
+  return GDI_MAGIC_TO_TYPE(ObjHdr->Magic);
 }
 
 /*!
@@ -445,11 +475,11 @@ GDIOBJ_GetHandleMagic (HGDIOBJ ObjectHandle)
 VOID FASTCALL
 InitGdiObjectHandleTable (VOID)
 {
-  DPRINT ("InitGdiObjectHandleTable\n");
+  DPRINT("InitGdiObjectHandleTable\n");
   ExInitializeFastMutex (&HandleTableMutex);
   ExInitializeFastMutex (&RefCountHandling);
 
-  HandleTable = GDIOBJ_iAllocHandleTable (GDI_HANDLE_NUMBER);
+  HandleTable = GDIOBJ_iAllocHandleTable (GDI_HANDLE_COUNT);
   DPRINT("HandleTable: %x\n", HandleTable );
 
   InitEngHandleTable();
@@ -461,42 +491,42 @@ InitGdiObjectHandleTable (VOID)
 VOID FASTCALL
 CreateStockObjects(void)
 {
-  // Create GDI Stock Objects from the logical structures we've defined
-
-  StockObjects[WHITE_BRUSH] =  W32kCreateBrushIndirect(&WhiteBrush);
-  GDIOBJ_MarkObjectGlobal(StockObjects[WHITE_BRUSH]);
-  StockObjects[LTGRAY_BRUSH] = W32kCreateBrushIndirect(&LtGrayBrush);
-  GDIOBJ_MarkObjectGlobal(StockObjects[LTGRAY_BRUSH]);
-  StockObjects[GRAY_BRUSH] =   W32kCreateBrushIndirect(&GrayBrush);
-  GDIOBJ_MarkObjectGlobal(StockObjects[GRAY_BRUSH]);
-  StockObjects[DKGRAY_BRUSH] = W32kCreateBrushIndirect(&DkGrayBrush);
-  GDIOBJ_MarkObjectGlobal(StockObjects[DKGRAY_BRUSH]);
-  StockObjects[BLACK_BRUSH] =  W32kCreateBrushIndirect(&BlackBrush);
-  GDIOBJ_MarkObjectGlobal(StockObjects[BLACK_BRUSH]);
-  StockObjects[NULL_BRUSH] =   W32kCreateBrushIndirect(&NullBrush);
-  GDIOBJ_MarkObjectGlobal(StockObjects[NULL_BRUSH]);
-
-  StockObjects[WHITE_PEN] = W32kCreatePenIndirect(&WhitePen);
-  GDIOBJ_MarkObjectGlobal(StockObjects[WHITE_PEN]);
-  StockObjects[BLACK_PEN] = W32kCreatePenIndirect(&BlackPen);
-  GDIOBJ_MarkObjectGlobal(StockObjects[BLACK_PEN]);
-  StockObjects[NULL_PEN] =  W32kCreatePenIndirect(&NullPen);
-  GDIOBJ_MarkObjectGlobal(StockObjects[NULL_PEN]);
+  unsigned Object;
+
+  DPRINT("Beginning creation of stock objects\n");
+
+  /* Create GDI Stock Objects from the logical structures we've defined */
+
+  StockObjects[WHITE_BRUSH] =  NtGdiCreateBrushIndirect(&WhiteBrush);
+  StockObjects[LTGRAY_BRUSH] = NtGdiCreateBrushIndirect(&LtGrayBrush);
+  StockObjects[GRAY_BRUSH] =   NtGdiCreateBrushIndirect(&GrayBrush);
+  StockObjects[DKGRAY_BRUSH] = NtGdiCreateBrushIndirect(&DkGrayBrush);
+  StockObjects[BLACK_BRUSH] =  NtGdiCreateBrushIndirect(&BlackBrush);
+  StockObjects[NULL_BRUSH] =   NtGdiCreateBrushIndirect(&NullBrush);
+
+  StockObjects[WHITE_PEN] = NtGdiCreatePenIndirect(&WhitePen);
+  StockObjects[BLACK_PEN] = NtGdiCreatePenIndirect(&BlackPen);
+  StockObjects[NULL_PEN] =  NtGdiCreatePenIndirect(&NullPen);
 
   (void) TextIntCreateFontIndirect(&OEMFixedFont, (HFONT*)&StockObjects[OEM_FIXED_FONT]);
-  GDIOBJ_MarkObjectGlobal(StockObjects[OEM_FIXED_FONT]);
   (void) TextIntCreateFontIndirect(&AnsiFixedFont, (HFONT*)&StockObjects[ANSI_FIXED_FONT]);
-  GDIOBJ_MarkObjectGlobal(StockObjects[ANSI_FIXED_FONT]);
   (void) TextIntCreateFontIndirect(&SystemFont, (HFONT*)&StockObjects[SYSTEM_FONT]);
-  GDIOBJ_MarkObjectGlobal(StockObjects[SYSTEM_FONT]);
   (void) TextIntCreateFontIndirect(&DeviceDefaultFont, (HFONT*)&StockObjects[DEVICE_DEFAULT_FONT]);
-  GDIOBJ_MarkObjectGlobal(StockObjects[DEVICE_DEFAULT_FONT]);
   (void) TextIntCreateFontIndirect(&SystemFixedFont, (HFONT*)&StockObjects[SYSTEM_FIXED_FONT]);
-  GDIOBJ_MarkObjectGlobal(StockObjects[SYSTEM_FIXED_FONT]);
   (void) TextIntCreateFontIndirect(&DefaultGuiFont, (HFONT*)&StockObjects[DEFAULT_GUI_FONT]);
-  GDIOBJ_MarkObjectGlobal(StockObjects[DEFAULT_GUI_FONT]);
 
   StockObjects[DEFAULT_PALETTE] = (HGDIOBJ*)PALETTE_Init();
+
+  for (Object = 0; Object < NB_STOCK_OBJECTS; Object++)
+    {
+      if (NULL != StockObjects[Object])
+       {
+         GDIOBJ_MarkObjectGlobal(StockObjects[Object]);
+/*       GDI_HANDLE_SET_STOCKOBJ(StockObjects[Object]);*/
+       }
+    }
+
+  DPRINT("Completed creation of stock objects\n");
 }
 
 /*!
@@ -505,23 +535,24 @@ CreateStockObjects(void)
  * \return     Handle to the object.
 */
 HGDIOBJ STDCALL
-W32kGetStockObject(INT  Object)
+NtGdiGetStockObject(INT Object)
 {
-  // check when adding new objects
-  if( (Object < 0) || (Object >= NB_STOCK_OBJECTS)  )
-       return NULL;
-  return StockObjects[Object];
+  DPRINT("NtGdiGetStockObject index %d\n", Object);
+
+  return ((Object < 0) || (NB_STOCK_OBJECTS <= Object)) ? NULL : StockObjects[Object];
 }
 
 /*!
  * Delete GDI object
  * \param      hObject object handle
- * \return     if the function fails the returned value is NULL.
+ * \return     if the function fails the returned value is FALSE.
 */
 BOOL STDCALL
-W32kDeleteObject(HGDIOBJ hObject)
+NtGdiDeleteObject(HGDIOBJ hObject)
 {
-  return GDIOBJ_FreeObj( hObject, GO_MAGIC_DONTCARE, GDIOBJFLAG_DEFAULT );
+  DPRINT("NtGdiDeleteObject handle 0x%08x\n", hObject);
+
+  return GDIOBJ_FreeObj(hObject, GDI_OBJECT_TYPE_DONTCARE, GDIOBJFLAG_DEFAULT);
 }
 
 /*!
@@ -532,26 +563,26 @@ BOOL FASTCALL
 CleanupForProcess (struct _EPROCESS *Process, INT Pid)
 {
   DWORD i;
-  PGDI_HANDLE_ENTRY handleEntry;
   PGDIOBJHDR objectHeader;
   PEPROCESS CurrentProcess;
-  //NTSTATUS Status;
 
+  DPRINT("Starting CleanupForProcess prochandle %x Pid %d\n", Process, Pid);
   CurrentProcess = PsGetCurrentProcess();
   if (CurrentProcess != Process)
     {
       KeAttachProcess(Process);
     }
 
-  for(i = 1; i < GDI_HANDLE_NUMBER; i++)
+  for(i = 1; i < HandleTable->wTableSize; i++)
     {
-      handleEntry = GDIOBJ_iGetHandleEntryForIndex((WORD) i & 0xffff);
-      if (NULL != handleEntry && 0 != handleEntry->wMagic &&
-          (INT)handleEntry->hProcessId == Pid)
+      objectHeader = GDIOBJ_iGetObjectForIndex(i);
+      if (NULL != objectHeader &&
+          (INT) objectHeader->hProcessId == Pid)
        {
-         objectHeader = (PGDIOBJHDR) handleEntry->pObject;
-         DPRINT("\nW32kCleanup: %d, magic: %x \n process: %d, locks: %d", i, handleEntry->wMagic, handleEntry->hProcessId, objectHeader->dwCount);
-         GDIOBJ_FreeObj( GDI_INDEX2HANDLE(i), GO_MAGIC_DONTCARE, GDIOBJFLAG_IGNOREPID|GDIOBJFLAG_IGNORELOCK );
+         DPRINT("CleanupForProcess: %d, process: %d, locks: %d, magic: 0x%x", i, objectHeader->hProcessId, objectHeader->dwCount, objectHeader->Magic);
+         GDIOBJ_FreeObj(GDI_HANDLE_CREATE(i, GDI_MAGIC_TO_TYPE(objectHeader->Magic)),
+                        GDI_MAGIC_TO_TYPE(objectHeader->Magic),
+                        GDIOBJFLAG_IGNOREPID | GDIOBJFLAG_IGNORELOCK);
        }
     }
 
@@ -560,29 +591,9 @@ CleanupForProcess (struct _EPROCESS *Process, INT Pid)
       KeDetachProcess();
     }
 
-  return TRUE;
-}
-
-/*!
- *     Internal function. Dumps all the objects for the given process.
- * \param      If process == 0 dump all the objects.
- *
-*/
-VOID STDCALL
-W32kDumpGdiObjects( INT Process )
-{
-       DWORD i;
-       PGDI_HANDLE_ENTRY handleEntry;
-       PGDIOBJHDR  objectHeader;
-
-       for( i=1; i < GDI_HANDLE_NUMBER; i++ ){
-               handleEntry = GDIOBJ_iGetHandleEntryForIndex ((WORD) i & 0xffff);
-               if( handleEntry && handleEntry->wMagic != 0 ){
-                       objectHeader = (PGDIOBJHDR) handleEntry->pObject;
-                       DPRINT("\nHandle: %d, magic: %x \n process: %d, locks: %d", i, handleEntry->wMagic, handleEntry->hProcessId, objectHeader->dwCount);
-               }
-       }
+  DPRINT("Completed cleanup for process %d\n", Pid);
 
+  return TRUE;
 }
 
 #define GDIOBJ_TRACKLOCKS
@@ -590,45 +601,50 @@ W32kDumpGdiObjects( INT Process )
 #ifdef GDIOBJ_LockObj
 #undef GDIOBJ_LockObj
 PGDIOBJ FASTCALL
-GDIOBJ_LockObjDbg ( const char* file, int line, HGDIOBJ hObj, WORD Magic )
+GDIOBJ_LockObjDbg (const char* file, int line, HGDIOBJ hObj, DWORD ObjectType)
 {
   PGDIOBJ rc;
-  PGDI_HANDLE_ENTRY handleEntry
-    = GDIOBJ_iGetHandleEntryForIndex ( GDI_HANDLE2INDEX(hObj) );
-  if ( handleEntry == 0
-       || (handleEntry->wMagic != Magic && Magic != GO_MAGIC_DONTCARE )
-       || (handleEntry->hProcessId != (HANDLE)0xFFFFFFFF
-          && handleEntry->hProcessId != PsGetCurrentProcessId ()
-         )
-     )
+  PGDIOBJHDR ObjHdr = GDIOBJ_iGetObjectForIndex(GDI_HANDLE_GET_INDEX(hObj));
+
+  if (! GDI_VALID_OBJECT(hObj, ObjHdr, ObjectType, GDIOBJFLAG_DEFAULT))
     {
       int reason = 0;
-      if ( handleEntry == 0 )
-       reason = 1;
-      else if ( handleEntry->wMagic != Magic && Magic != GO_MAGIC_DONTCARE )
-       reason = 2;
-      else if ( handleEntry->hProcessId != (HANDLE)0xFFFFFFFF
-          && handleEntry->hProcessId != PsGetCurrentProcessId () )
-       reason = 3;
-
-      DPRINT1("GDIOBJ_LockObj failed for %d, magic: %d, reqMagic %d reason %d\n",
-                 (WORD)((size_t)hObj&0xffff), handleEntry->wMagic, Magic, reason );
+      if (NULL == ObjHdr)
+       {
+         reason = 1;
+       }
+      else if (GDI_MAGIC_TO_TYPE(ObjHdr->Magic) != ObjectType && ObjectType != GDI_OBJECT_TYPE_DONTCARE)
+       {
+         reason = 2;
+       }
+      else if (ObjHdr->hProcessId != GDI_GLOBAL_PROCESS
+          && ObjHdr->hProcessId != PsGetCurrentProcessId())
+       {
+         reason = 3;
+       }
+      else if (GDI_HANDLE_GET_TYPE(hObj) != ObjectType && ObjectType != GDI_OBJECT_TYPE_DONTCARE)
+       {
+         reason = 4;
+       }
+      DPRINT1("GDIOBJ_LockObj failed for 0x%08x, reqtype 0x%08x reason %d\n",
+              hObj, ObjectType, reason );
       DPRINT1("\tcalled from: %s:%i\n", file, line );
-      return  NULL;
+      return NULL;
     }
-  if ( handleEntry->lockfile )
+  if (NULL != ObjHdr->lockfile)
     {
       DPRINT1("Caution! GDIOBJ_LockObj trying to lock object (0x%x) second time\n", hObj );
       DPRINT1("\tcalled from: %s:%i\n", file, line );
-      DPRINT1("\tpreviously locked from: %s:%i\n", handleEntry->lockfile, handleEntry->lockline );
+      DPRINT1("\tpreviously locked from: %s:%i\n", ObjHdr->lockfile, ObjHdr->lockline );
     }
-  //DbgPrint("(%s:%i) GDIOBJ_LockObj(0x%x,0x%x)\n", file, line, hObj, Magic );
-  rc = GDIOBJ_LockObj(hObj,Magic);
-  if ( rc && !handleEntry->lockfile )
+  DPRINT("(%s:%i) GDIOBJ_LockObj(0x%08x,0x%08x)\n", file, line, hObj, ObjectType);
+  rc = GDIOBJ_LockObj(hObj, ObjectType);
+  if (rc && NULL == ObjHdr->lockfile)
     {
-      handleEntry->lockfile = file;
-      handleEntry->lockline = line;
+      ObjHdr->lockfile = file;
+      ObjHdr->lockline = line;
     }
+
   return rc;
 }
 #endif//GDIOBJ_LockObj
@@ -636,26 +652,22 @@ GDIOBJ_LockObjDbg ( const char* file, int line, HGDIOBJ hObj, WORD Magic )
 #ifdef GDIOBJ_UnlockObj
 #undef GDIOBJ_UnlockObj
 BOOL FASTCALL
-GDIOBJ_UnlockObjDbg ( const char* file, int line, HGDIOBJ hObj, WORD Magic )
+GDIOBJ_UnlockObjDbg (const char* file, int line, HGDIOBJ hObj, DWORD ObjectType)
 {
-  PGDI_HANDLE_ENTRY handleEntry
-    = GDIOBJ_iGetHandleEntryForIndex ( GDI_HANDLE2INDEX(hObj) );
-  if ( handleEntry == 0
-       || (handleEntry->wMagic != Magic && Magic != GO_MAGIC_DONTCARE )
-       || (handleEntry->hProcessId != (HANDLE)0xFFFFFFFF
-           && handleEntry->hProcessId != PsGetCurrentProcessId ()
-         )
-     )
+  PGDIOBJHDR ObjHdr = GDIOBJ_iGetObjectForIndex(GDI_HANDLE_GET_INDEX(hObj));
+
+  if (! GDI_VALID_OBJECT(hObj, ObjHdr, ObjectType, GDIOBJFLAG_DEFAULT))
     {
-      DPRINT1("GDIBOJ_UnlockObj failed for %d, magic: %d, reqMagic\n",
-                 (WORD)((size_t)hObj & 0xffff), handleEntry->wMagic, Magic );
-      DPRINT1("\tcalled from: %s:%i\n", file, line );
+      DPRINT1("GDIBOJ_UnlockObj failed for 0x%08x, reqtype 0x%08x\n",
+                 hObj, ObjectType);
+      DPRINT1("\tcalled from: %s:%i\n", file, line);
       return FALSE;
     }
-  //DbgPrint("(%s:%i) GDIOBJ_UnlockObj(0x%x,0x%x)\n", file, line, hObj, Magic );
-  handleEntry->lockfile = NULL;
-  handleEntry->lockline = 0;
-  return GDIOBJ_UnlockObj(hObj,Magic);
+  DPRINT("(%s:%i) GDIOBJ_UnlockObj(0x%08x,0x%08x)\n", file, line, hObj, ObjectType);
+  ObjHdr->lockfile = NULL;
+  ObjHdr->lockline = 0;
+
+  return GDIOBJ_UnlockObj(hObj, ObjectType);
 }
 #endif//GDIOBJ_LockObj
 
@@ -663,45 +675,36 @@ GDIOBJ_UnlockObjDbg ( const char* file, int line, HGDIOBJ hObj, WORD Magic )
  * Return pointer to the object by handle.
  *
  * \param hObj                 Object handle
- * \param Magic                one of the magic numbers defined in \ref GDI Magic
- * \return                     Pointer to the object.
+ * \param ObjectType   one of the object types defined in \ref GDI object types
+ * \return             Pointer to the object.
  *
  * \note Process can only get pointer to the objects it created or global objects.
  *
  * \todo Don't allow to lock the objects twice! Synchronization!
 */
 PGDIOBJ FASTCALL
-GDIOBJ_LockObj( HGDIOBJ hObj, WORD Magic )
+GDIOBJ_LockObj(HGDIOBJ hObj, DWORD ObjectType)
 {
-  PGDI_HANDLE_ENTRY handleEntry
-    = GDIOBJ_iGetHandleEntryForIndex ( GDI_HANDLE2INDEX(hObj) );
-  PGDIOBJHDR  objectHeader;
-
-  DPRINT("GDIOBJ_LockObj: hObj: %d, magic: %x, \n handleEntry: %x, mag %x\n", hObj, Magic, handleEntry, handleEntry->wMagic);
-  if ( handleEntry == 0
-       || (handleEntry->wMagic != Magic && Magic != GO_MAGIC_DONTCARE )
-       || (handleEntry->hProcessId != (HANDLE)0xFFFFFFFF
-           && handleEntry->hProcessId != PsGetCurrentProcessId ()
-         )
-     )
+  PGDIOBJHDR ObjHdr = GDIOBJ_iGetObjectForIndex(GDI_HANDLE_GET_INDEX(hObj));
+
+  DPRINT("GDIOBJ_LockObj: hObj: 0x%08x, type: 0x%08x, objhdr: %x\n", hObj, ObjectType, ObjHdr);
+  if (! GDI_VALID_OBJECT(hObj, ObjHdr, ObjectType, GDIOBJFLAG_DEFAULT))
     {
-      DPRINT1("GDIBOJ_LockObj failed for %d, magic: %d, reqMagic\n",
-                 (WORD)((size_t)hObj & 0xffff), handleEntry->wMagic, Magic);
+      DPRINT1("GDIBOJ_LockObj failed for 0x%08x, type 0x%08x\n",
+                 hObj, ObjectType);
       return NULL;
     }
 
-  objectHeader = (PGDIOBJHDR) handleEntry->pObject;
-  ASSERT(objectHeader);
-  if( objectHeader->dwCount > 0 )
+  if(0 < ObjHdr->dwCount)
     {
-      DbgPrint("Caution! GDIOBJ_LockObj trying to lock object (0x%x) second time\n", hObj );
-      DbgPrint("\t called from: %x\n", __builtin_return_address(0));
+      DPRINT1("Caution! GDIOBJ_LockObj trying to lock object (0x%x) second time\n", hObj);
+      DPRINT1("\t called from: %x\n", __builtin_return_address(0));
     }
 
   ExAcquireFastMutex(&RefCountHandling);
-  objectHeader->dwCount++;
+  ObjHdr->dwCount++;
   ExReleaseFastMutex(&RefCountHandling);
-  return (PGDIOBJ)((PCHAR)objectHeader + sizeof(GDIOBJHDR));
+  return (PGDIOBJ)((PCHAR)ObjHdr + sizeof(GDIOBJHDR));
 }
 
 /*!
@@ -709,7 +712,7 @@ GDIOBJ_LockObj( HGDIOBJ hObj, WORD Magic )
  * as soon as you don't need to have access to it's data.
 
  * \param hObj                 Object handle
- * \param Magic                one of the magic numbers defined in \ref GDI Magic
+ * \param ObjectType   one of the object types defined in \ref GDI object types
  *
  * \note This function performs delayed cleanup. If the object is locked when GDI_FreeObj() is called
  * then \em this function frees the object when reference count is zero.
@@ -718,48 +721,38 @@ GDIOBJ_LockObj( HGDIOBJ hObj, WORD Magic )
 */
 #undef GDIOBJ_UnlockObj
 BOOL FASTCALL
-GDIOBJ_UnlockObj( HGDIOBJ hObj, WORD Magic )
+GDIOBJ_UnlockObj(HGDIOBJ hObj, DWORD ObjectType)
 {
-  PGDI_HANDLE_ENTRY handleEntry
-    = GDIOBJ_iGetHandleEntryForIndex ( GDI_HANDLE2INDEX(hObj) );
-  PGDIOBJHDR  objectHeader;
-
-  DPRINT("GDIOBJ_UnlockObj: hObj: %d, magic: %x, \n handleEntry: %x\n", hObj, Magic, handleEntry);
-  if ( handleEntry == 0
-     || (handleEntry->wMagic != Magic && Magic != GO_MAGIC_DONTCARE )
-     || (handleEntry->hProcessId != (HANDLE)0xFFFFFFFF
-         && handleEntry->hProcessId != PsGetCurrentProcessId ()
-       )
-     )
-  {
+  PGDIOBJHDR ObjHdr = GDIOBJ_iGetObjectForIndex(GDI_HANDLE_GET_INDEX(hObj));
+
+  DPRINT("GDIOBJ_UnlockObj: hObj: 0x%08x, type: 0x%08x, objhdr: %x\n", hObj, ObjectType, ObjHdr);
+  if (! GDI_VALID_OBJECT(hObj, ObjHdr, ObjectType, GDIOBJFLAG_DEFAULT))
+    {
     DPRINT1( "GDIOBJ_UnLockObj: failed\n");
     return FALSE;
   }
 
-  objectHeader = (PGDIOBJHDR) handleEntry->pObject;
-  ASSERT(objectHeader);
-
   ExAcquireFastMutex(&RefCountHandling);
-  if( ( objectHeader->dwCount & ~0x80000000 ) == 0 )
+  if (0 == (ObjHdr->dwCount & ~0x80000000))
     {
       ExReleaseFastMutex(&RefCountHandling);
-      DPRINT( "GDIOBJ_UnLockObj: unlock object (0x%x) that is not locked\n", hObj );
+      DPRINT1( "GDIOBJ_UnLockObj: unlock object (0x%x) that is not locked\n", hObj );
       return FALSE;
     }
 
-  objectHeader = (PGDIOBJHDR) handleEntry->pObject;
-  ASSERT(objectHeader);
-  objectHeader->dwCount--;
+  ObjHdr->dwCount--;
 
-  if( objectHeader->dwCount  == 0x80000000 )
+  if (ObjHdr->dwCount == 0x80000000)
     {
       //delayed object release
-      objectHeader->dwCount = 0;
+      ObjHdr->dwCount = 0;
       ExReleaseFastMutex(&RefCountHandling);
       DPRINT("GDIOBJ_UnlockObj: delayed delete\n");
-      return GDIOBJ_FreeObj( hObj, Magic, GDIOBJFLAG_DEFAULT );
+      return GDIOBJ_FreeObj(hObj, ObjectType, GDIOBJFLAG_DEFAULT);
     }
   ExReleaseFastMutex(&RefCountHandling);
+
   return TRUE;
 }
+
 /* EOF */