[CMAKE]
[reactos.git] / subsystems / win32 / win32k / objects / gdiobj.c
index a5c3723..5eb43dd 100644 (file)
@@ -8,9 +8,9 @@
 
 /** INCLUDES ******************************************************************/
 
-#define GDI_DEBUG
+//#define GDI_DEBUG
 
-#include <w32k.h>
+#include <win32k.h>
 #define NDEBUG
 #include <debug.h>
 
@@ -81,6 +81,8 @@ OBJ_TYPE_INFO ObjTypeInfo[BASE_OBJTYPE_COUNT] =
 };
 
 static LARGE_INTEGER ShortDelay;
+PGDI_HANDLE_TABLE GdiHandleTable = NULL;
+PSECTION_OBJECT GdiTableSection = NULL;
 
 /** INTERNAL FUNCTIONS ********************************************************/
 
@@ -151,7 +153,9 @@ GDI_CleanupDummy(PVOID ObjectBody)
  * Allocate GDI object table.
  * \param      Size - number of entries in the object table.
 */
-PGDI_HANDLE_TABLE INTERNAL_CALL
+INIT_FUNCTION
+PGDI_HANDLE_TABLE
+INTERNAL_CALL
 GDIOBJ_iAllocHandleTable(OUT PSECTION_OBJECT *SectionObject)
 {
     PGDI_HANDLE_TABLE HandleTable = NULL;
@@ -221,6 +225,23 @@ GDIOBJ_iAllocHandleTable(OUT PSECTION_OBJECT *SectionObject)
     return HandleTable;
 }
 
+INIT_FUNCTION
+NTSTATUS
+NTAPI
+InitGdiHandleTable()
+{
+    /* Create the GDI handle table */
+    GdiHandleTable = GDIOBJ_iAllocHandleTable(&GdiTableSection);
+    if (GdiHandleTable == NULL)
+    {
+        DPRINT1("Failed to initialize the GDI handle table.\n");
+        return STATUS_UNSUCCESSFUL;
+    }
+
+    return STATUS_SUCCESS;
+}
+
+
 static void FASTCALL
 LockErrorDebugOutput(HGDIOBJ hObj, PGDI_TABLE_ENTRY Entry, LPSTR Function)
 {
@@ -631,11 +652,22 @@ LockHandle:
             }
             else if (Object->ulShareCount != 0)
             {
+                NTSTATUS Status;
+                PEPROCESS OldProcess;
                 Object->BaseFlags |= BASEFLAG_READY_TO_DIE;
                 DPRINT("Object %p, ulShareCount = %d\n", Object->hHmgr, Object->ulShareCount);
-                //GDIDBG_TRACECALLER();
-                //GDIDBG_TRACESHARELOCKER(GDI_HANDLE_GET_INDEX(hObj));
-                (void)InterlockedExchangePointer((PVOID*)&Entry->ProcessId, PrevProcId);
+                /* Set NULL owner. Do the work here to avoid race conditions */
+                Status = PsLookupProcessByProcessId((HANDLE)((ULONG_PTR)PrevProcId & ~0x1), &OldProcess);
+                if (NT_SUCCESS(Status))
+                {
+                    PPROCESSINFO W32Process = (PPROCESSINFO)OldProcess->Win32Process;
+                    if (W32Process != NULL)
+                    {
+                        InterlockedDecrement(&W32Process->GDIHandleCount);
+                    }
+                    ObDereferenceObject(OldProcess);
+                }
+                (void)InterlockedExchangePointer((PVOID*)&Entry->ProcessId, NULL);
                 /* Don't wait on shared locks */
                 return FALSE;
             }
@@ -646,7 +678,7 @@ LockHandle:
                  */
                 DPRINT1("Object->cExclusiveLock = %d\n", Object->cExclusiveLock);
                 GDIDBG_TRACECALLER();
-                GDIDBG_TRACELOCKER(GDI_HANDLE_GET_INDEX(hObj));
+                GDIDBG_TRACELOCKER(hObj);
                 (void)InterlockedExchangePointer((PVOID*)&Entry->ProcessId, PrevProcId);
                 /* do not assert here for it will call again from dxg.sys it being call twice */
 
@@ -688,7 +720,7 @@ LockHandle:
             }
             DPRINT1("Type = 0x%lx, KernelData = 0x%p, ProcessId = 0x%p\n", Entry->Type, Entry->KernelData, Entry->ProcessId);
             GDIDBG_TRACECALLER();
-            GDIDBG_TRACEALLOCATOR(GDI_HANDLE_GET_INDEX(hObj));
+            GDIDBG_TRACEALLOCATOR(hObj);
         }
     }
 
@@ -952,6 +984,10 @@ GDIOBJ_LockObj(HGDIOBJ hObj, DWORD ExpectedType)
     POBJ Object = NULL;
     ULONG HandleType, HandleUpper;
 
+    /* Check for dummy call */
+    if(hObj == NULL)
+        return NULL ;
+
     GDIDBG_INITLOOPTRACE();
 
     HandleIndex = GDI_HANDLE_GET_INDEX(hObj);
@@ -959,7 +995,7 @@ GDIOBJ_LockObj(HGDIOBJ hObj, DWORD ExpectedType)
     HandleUpper = GDI_HANDLE_GET_UPPER(hObj);
 
     /* Check that the handle index is valid. */
-    if (HandleIndex >= GDI_HANDLE_COUNT)
+    if (HandleIndex >= GDI_HANDLE_COUNT )
         return NULL;
 
     Entry = &GdiHandleTable->Entries[HandleIndex];
@@ -985,7 +1021,7 @@ GDIOBJ_LockObj(HGDIOBJ hObj, DWORD ExpectedType)
     {
         DPRINT1("Tried to lock object (0x%p) of wrong owner! ProcessId = %p, HandleProcessId = %p\n", hObj, ProcessId, HandleProcessId);
         GDIDBG_TRACECALLER();
-        GDIDBG_TRACEALLOCATOR(GDI_HANDLE_GET_INDEX(hObj));
+        GDIDBG_TRACEALLOCATOR(hObj);
         return NULL;
     }
 
@@ -1033,11 +1069,6 @@ GDIOBJ_LockObj(HGDIOBJ hObj, DWORD ExpectedType)
                 {
                     if (Object->Tid != Thread)
                     {
-                        GDIDBG_TRACELOOP(hObj, Object->Tid, Thread);
-                        GDIDBG_TRACECALLER();
-                        GDIDBG_TRACELOCKER(GDI_HANDLE_GET_INDEX(hObj));
-                        GDIDBG_TRACEALLOCATOR(GDI_HANDLE_GET_INDEX(hObj));
-
                         /* Unlock the handle table entry. */
                         (void)InterlockedExchangePointer((PVOID*)&Entry->ProcessId, PrevProcId);
 
@@ -1099,6 +1130,10 @@ GDIOBJ_ShareLockObj(HGDIOBJ hObj, DWORD ExpectedType)
     POBJ Object = NULL;
     ULONG_PTR HandleType, HandleUpper;
 
+    /* Check for dummy call */
+    if(hObj == NULL)
+        return NULL ;
+
     HandleIndex = GDI_HANDLE_GET_INDEX(hObj);
     HandleType = GDI_HANDLE_GET_TYPE(hObj);
     HandleUpper = GDI_HANDLE_GET_UPPER(hObj);
@@ -1398,6 +1433,19 @@ LockHandle:
                     PPROCESSINFO W32Process;
                     NTSTATUS Status;
 
+                    if (NewOwner != NULL)
+                    {
+                        ProcessId = PsGetProcessId(NewOwner);
+                    }
+                    else
+                        ProcessId = 0;
+
+                    if((ULONG_PTR)ProcessId == ((ULONG_PTR)PrevProcId & ~0x1))
+                    {
+                        DPRINT("Setting same process than previous one, nothing to do\n");
+                        goto done;
+                    }
+
                     /* dereference the process' object counter */
                     /* FIXME */
                     if ((ULONG_PTR)PrevProcId & ~0x1)
@@ -1416,8 +1464,6 @@ LockHandle:
 
                     if (NewOwner != NULL)
                     {
-                        ProcessId = PsGetProcessId(NewOwner);
-
                         /* Increase the new process' object counter */
                         W32Process = (PPROCESSINFO)NewOwner->Win32Process;
                         if (W32Process != NULL)
@@ -1425,9 +1471,8 @@ LockHandle:
                             InterlockedIncrement(&W32Process->GDIHandleCount);
                         }
                     }
-                    else
-                        ProcessId = 0;
 
+                done:
                     /* remove the process id lock and change it to the new process id */
                     (void)InterlockedExchangePointer((PVOID*)&Entry->ProcessId, ProcessId);
 
@@ -1625,39 +1670,35 @@ GDI_MapHandleTable(PSECTION_OBJECT SectionObject, PEPROCESS Process)
     return MappedView;
 }
 
-/* Locks up to 3 objects at a time */
+/* Locks 2 or 3 objects at a time */
 VOID
 INTERNAL_CALL
 GDIOBJ_LockMultipleObjs(ULONG ulCount,
                         IN HGDIOBJ* ahObj,
                         OUT PGDIOBJ* apObj)
 {
-    UINT iFirst = 0, iSecond = 0, iThird = 0;
-    UINT i ;
+    UINT auiIndices[3] = {0,1,2};
+    UINT i, tmp ;
+    BOOL bUnsorted = TRUE;
 
     /* First is greatest */
-    for(i=1; i<ulCount; i++)
+    while(bUnsorted)
     {
-        if((ULONG_PTR)ahObj[i] >= (ULONG_PTR)ahObj[iFirst])
-        {
-            iSecond = iFirst ;
-            iFirst = i;
-            continue ;
-        }
-        if((ULONG_PTR)ahObj[i] >= (ULONG_PTR)ahObj[iSecond])
+        bUnsorted = FALSE;
+        for(i=1; i<ulCount; i++)
         {
-            iSecond = i;
-            continue;
+            if((ULONG_PTR)ahObj[auiIndices[i-1]] < (ULONG_PTR)ahObj[auiIndices[i]])
+            {
+                tmp = auiIndices[i-1];
+                auiIndices[i-1] = auiIndices[i];
+                auiIndices[i] = tmp;
+                bUnsorted = TRUE;
+            }
         }
-        iThird = i;
     }
 
-    /* We consider that at least two handles were passed */
-    apObj[iFirst] = GDIOBJ_LockObj(ahObj[iFirst], GDI_OBJECT_TYPE_DONTCARE);
-    apObj[iSecond] = GDIOBJ_LockObj(ahObj[iSecond], GDI_OBJECT_TYPE_DONTCARE);
-    if(ulCount == 3)
-        apObj[iThird] = GDIOBJ_LockObj(ahObj[iThird], GDI_OBJECT_TYPE_DONTCARE);
-
+    for(i=0;i<ulCount;i++)
+        apObj[auiIndices[i]] = GDIOBJ_LockObj(ahObj[auiIndices[i]], GDI_OBJECT_TYPE_DONTCARE);
 }