Patch, as suggested by Mike Nordell, to verify IRQL before calling unsafe fast mutex...
[reactos.git] / reactos / subsys / win32k / objects / gdiobj.c
index 16b22ec..f6c80d3 100644 (file)
@@ -19,7 +19,7 @@
 /*
  * GDIOBJ.C - GDI object manipulation routines
  *
- * $Id: gdiobj.c,v 1.41 2003/09/09 10:57:03 gvg Exp $
+ * $Id: gdiobj.c,v 1.46 2003/10/15 03:09:23 vizzini Exp $
  *
  */
 
 #define NDEBUG
 #include <win32k/debug1.h>
 
+/*! 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)
 
-#define GDI_HANDLE_INDEX_MASK 0x00000fff
+#define GDI_HANDLE_INDEX_MASK (GDI_HANDLE_COUNT - 1)
 #define GDI_HANDLE_TYPE_MASK  0x007f0000
 #define GDI_HANDLE_STOCK_MASK 0x00800000
 
@@ -60,7 +66,7 @@
 #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)) == (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)))
@@ -140,12 +146,6 @@ static PGDI_HANDLE_TABLE  HandleTable = 0;
 static FAST_MUTEX  HandleTableMutex;
 static FAST_MUTEX  RefCountHandling;
 
-/*! 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_NUMBER  0x4000
-
 /*!
  * Allocate GDI object table.
  * \param      Size - number of entries in the object table.
@@ -154,6 +154,14 @@ static PGDI_HANDLE_TABLE FASTCALL
 GDIOBJ_iAllocHandleTable (WORD Size)
 {
   PGDI_HANDLE_TABLE  handleTable;
+  KIRQL OldIrql;
+  BOOLEAN IrqlRaised = FALSE;
+
+  if(KeGetCurrentIrql() < APC_LEVEL)
+    {
+      KeRaiseIrql(APC_LEVEL, &OldIrql);
+      IrqlRaised = TRUE;
+    }
 
   ExAcquireFastMutexUnsafe (&HandleTableMutex);
   handleTable = ExAllocatePool(PagedPool,
@@ -166,6 +174,9 @@ GDIOBJ_iAllocHandleTable (WORD Size)
   handleTable->wTableSize = Size;
   ExReleaseFastMutexUnsafe (&HandleTableMutex);
 
+  if(IrqlRaised)
+    KeLowerIrql(OldIrql);
+
   return handleTable;
 }
 
@@ -192,6 +203,14 @@ static WORD FASTCALL
 GDIOBJ_iGetNextOpenHandleIndex (void)
 {
   WORD tableIndex;
+  BOOLEAN IrqlRaised = FALSE;
+  KIRQL OldIrql;
+
+  if(KeGetCurrentIrql() < APC_LEVEL)
+    {
+      KeRaiseIrql(APC_LEVEL, &OldIrql);
+      IrqlRaised = TRUE;
+    }
 
   ExAcquireFastMutexUnsafe (&HandleTableMutex);
   for (tableIndex = 1; tableIndex < HandleTable->wTableSize; tableIndex++)
@@ -204,6 +223,9 @@ GDIOBJ_iGetNextOpenHandleIndex (void)
     }
   ExReleaseFastMutexUnsafe (&HandleTableMutex);
 
+  if(IrqlRaised)
+    KeLowerIrql(OldIrql);
+
   return (tableIndex < HandleTable->wTableSize) ? tableIndex : 0;
 }
 
@@ -223,8 +245,16 @@ HGDIOBJ FASTCALL
 GDIOBJ_AllocObj(WORD Size, DWORD ObjectType, GDICLEANUPPROC CleanupProc)
 {
   PGDIOBJHDR  newObject;
+  WORD Index;
+  
+  Index = GDIOBJ_iGetNextOpenHandleIndex ();
+  if (0 == Index)
+    {
+      DPRINT1("Out of GDI handles\n");
+      return NULL;
+    }
 
-  DPRINT("GDIOBJ_AllocObj: size: %d, type: 0x%08x\n", Size, ObjectType);
+  DPRINT("GDIOBJ_AllocObj: handle: %d, size: %d, type: 0x%08x\n", Index, Size, ObjectType);
   newObject = ExAllocatePool(PagedPool, Size + sizeof (GDIOBJHDR));
   if (newObject == NULL)
   {
@@ -233,14 +263,7 @@ GDIOBJ_AllocObj(WORD Size, DWORD ObjectType, GDICLEANUPPROC CleanupProc)
   }
   RtlZeroMemory (newObject, Size + sizeof(GDIOBJHDR));
 
-  newObject->wTableIndex = GDIOBJ_iGetNextOpenHandleIndex ();
-  DPRINT("GDIOBJ_AllocObj: object handle %d\n", newObject->wTableIndex );
-  if (0 == newObject->wTableIndex)
-    {
-      DPRINT1("Out of GDI handles\n");
-      ExFreePool(newObject);
-      return NULL;
-    }
+  newObject->wTableIndex = Index;
 
   newObject->dwCount = 0;
   newObject->hProcessId = PsGetCurrentProcessId ();
@@ -248,9 +271,9 @@ GDIOBJ_AllocObj(WORD Size, DWORD ObjectType, GDICLEANUPPROC CleanupProc)
   newObject->Magic = GDI_TYPE_TO_MAGIC(ObjectType);
   newObject->lockfile = NULL;
   newObject->lockline = 0;
-  HandleTable->Handles[newObject->wTableIndex] = newObject;
+  HandleTable->Handles[Index] = newObject;
 
-  return GDI_HANDLE_CREATE(newObject->wTableIndex, ObjectType);
+  return GDI_HANDLE_CREATE(Index, ObjectType);
 }
 
 /*!
@@ -449,7 +472,8 @@ GDIOBJ_GetObjectType(HGDIOBJ ObjectHandle)
   PGDIOBJHDR ObjHdr;
 
   ObjHdr = GDIOBJ_iGetObjectForIndex(GDI_HANDLE_GET_INDEX(ObjectHandle));
-  if (NULL == ObjHdr)
+  if (NULL == ObjHdr
+      || ! GDI_VALID_OBJECT(ObjectHandle, ObjHdr, GDI_MAGIC_TO_TYPE(ObjHdr->Magic), 0))
     {
       DPRINT1("Invalid ObjectHandle 0x%08x\n", ObjectHandle);
       return 0;
@@ -470,7 +494,7 @@ InitGdiObjectHandleTable (VOID)
   ExInitializeFastMutex (&HandleTableMutex);
   ExInitializeFastMutex (&RefCountHandling);
 
-  HandleTable = GDIOBJ_iAllocHandleTable (GDI_HANDLE_NUMBER);
+  HandleTable = GDIOBJ_iAllocHandleTable (GDI_HANDLE_COUNT);
   DPRINT("HandleTable: %x\n", HandleTable );
 
   InitEngHandleTable();
@@ -571,8 +595,8 @@ CleanupForProcess (struct _EPROCESS *Process, INT Pid)
           (INT) objectHeader->hProcessId == Pid)
        {
          DPRINT("CleanupForProcess: %d, process: %d, locks: %d, magic: 0x%x", i, objectHeader->hProcessId, objectHeader->dwCount, objectHeader->Magic);
-         GDIOBJ_FreeObj(GDI_HANDLE_CREATE(i, GDI_OBJECT_TYPE_DONTCARE),
-                        GDI_OBJECT_TYPE_DONTCARE,
+         GDIOBJ_FreeObj(GDI_HANDLE_CREATE(i, GDI_MAGIC_TO_TYPE(objectHeader->Magic)),
+                        GDI_MAGIC_TO_TYPE(objectHeader->Magic),
                         GDIOBJFLAG_IGNOREPID | GDIOBJFLAG_IGNORELOCK);
        }
     }