/** INCLUDES ******************************************************************/
-#define GDI_DEBUG
+//#define GDI_DEBUG
-#include <w32k.h>
+#include <win32k.h>
#define NDEBUG
#include <debug.h>
};
static LARGE_INTEGER ShortDelay;
+PGDI_HANDLE_TABLE GdiHandleTable = NULL;
+PSECTION_OBJECT GdiTableSection = NULL;
/** INTERNAL FUNCTIONS ********************************************************/
* 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;
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)
{
}
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;
}
*/
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 */
}
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);
}
}
POBJ Object = NULL;
ULONG HandleType, HandleUpper;
+ /* Check for dummy call */
+ if(hObj == NULL)
+ return NULL ;
+
GDIDBG_INITLOOPTRACE();
HandleIndex = GDI_HANDLE_GET_INDEX(hObj);
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];
{
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;
}
{
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);
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);
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)
if (NewOwner != NULL)
{
- ProcessId = PsGetProcessId(NewOwner);
-
/* Increase the new process' object counter */
W32Process = (PPROCESSINFO)NewOwner->Win32Process;
if (W32Process != NULL)
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);
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);
}